(1)服务器段代码如下:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <time.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define BUFSIZE 512
/*
* 错误报告
*/
static void bail(const char *on_what){
fputs(strerror(errno), stderr);
fputs(": ", stderr);
fputs(on_what, stderr);
fputc('\n', stderr);
exit(1);
}
int main(int argc, char *argv[]){
int sockfd; /* 服务器套接字 */
int new_fd; /* 服务器连接套接字 */
struct sockaddr_in server_addr; /* 服务器监听套接字 */
struct sockaddr_in client_addr; /* 客户端IP地址 */
socklen_t size;
int portnumber;
char reqBuf[BUFSIZE]; /* 应用接收缓存 */
char dtfmt[BUFSIZE]; /* 日期-时间结果字符串 */
time_t td; /* 当前日期和时间 */
struct tm tm; /* 日期时间结构体 */
int z;
if(argc != 2){
fprintf(stderr, "Usage: %s portnumber\a\n", argv[0]);
exit(1);
}
if((portnumber = atoi(argv[1]))<0){
fprintf(stderr, "Usage: %s portnumber\a\n", argv[0]);
exit(1);
}
/* 创建服务器监听套接字 */
if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1){
fprintf(stderr, "Socket error: %s\a\n",
strerror(errno));
exit(1);
}
/* 为监听套接字准备IP地址和端口 */
memset(&server_addr, 0, sizeof server_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(portnumber);
/* 绑定套接字到指定地址和端口 */
if ((bind (sockfd, (struct sockaddr *)(&server_addr),
sizeof server_addr)) == -1){
fprintf(stderr, "Bind error: %s\a\n", strerror(errno));
exit(1);
}
/* 监听 */
if (listen(sockfd, 128) == -1) {
fprintf(stderr, "Listen error: %s\n\a",
strerror(errno));
exit(1);
}
printf("waiting for the client's request...\n");
/* 服务器主循环处理 */
while (1) {
size = sizeof (struct sockaddr_in);
/* 接收一个客户端连接并创建服务器连接套接字 */
if((new_fd = accept(sockfd,
(struct sockaddr *)(&client_addr), &size)) == -1){
fprintf(stderr, "Accept error: %s\a\n",
strerror(errno));
exit(1);
}
fprintf(stdout, "Server got connection from %s\n",
inet_ntoa(client_addr.sin_addr));
for(;;) {
/* 读取客户端发来的日期时间请求,若客户端没有发送请求,
* 则服务器将阻塞
*/
z = read (new_fd, reqBuf, sizeof reqBuf);
if(z < 0)
bail("read()");
/* 服务器检查客户端是否关闭了套接字,此时read操作
* 返回0(EOF )。如果客户端关闭了其套接字,则服务器
* 将执行close 结束此连接,然后开始接收下一个客户端
* 的连接请求
*/
if(z == 0) {
close (new_fd);
break;
}
/*
* 向请求连接字符串尾添加NULL字符构成完整的请求日
* 期时间字符串
*/
reqBuf[z] = 0;
/*
* 获得服务器当前日期和时间
*/
time(&td);
tm = *localtime(&td);
/*
* 根据请求日期字符串的格式字串生成应答字符串
*/
strftime(dtfmt, /* 格式化结果 */
sizeof dtfmt,
reqBuf, /* 客户端请求格式字串 */
&tm);
/* 将格式化结果发送给客户端 */
z = write (new_fd, dtfmt, strlen(dtfmt));
if(z < 0)
bail("write()");
}
}
}
(2)客户端代码:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#define BUFSIZE 512
static void bail(const char *on_what){
fputs(strerror(errno), stderr);
fputs(": ", stderr);
fputs(on_what, stderr);
fputc('\n', stderr);
exit(1);
}
int main (int argc, char *argv[]) {
int sockfd; /*客户端套接字*/
char buf[BUFSIZE];
struct sockaddr_in server_addr; /* 服务器IP地址*/
struct hostent *host;
int portnumber;
int nbytes;
int z;
char reqBuf[BUFSIZE]; /*客户端请求格式字符串 */
if (argc != 3) {
fprintf(stderr, "Usage: %s hostname portnumber\a\n",
argv[0]);
exit(1);
}
if ((host = gethostbyname(argv[1])) == NULL) {
fprintf(stderr, "Gethostname error\n");
exit(1);
}
if ((portnumber = atoi(argv[2])) < 0) {
fprintf(stderr, "Usage: %s hostname portnumber\a\n",
argv[0]);
exit(1);
}
/*创建套接字 */
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
fprintf(stderr, "Socket Error: %s\a\n",
strerror(errno));
exit(1);
}
/* 创建服务器地址*/
memset(&server_addr, 0, sizeof server_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(portnumber);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
/*链接服务器*/
if (connect(sockfd, (struct sockaddr *)(&server_addr),
sizeof server_addr) == -1) {
fprintf(stderr, "Connect Error: %s\a\n",
strerror(errno));
exit(1);
}
printf("connected to server %s\n",
inet_ntoa(server_addr.sin_addr));
/*
*客户端程序主循环,输入‘quit’退出
*/
for (;;) {
/* 提示输入日期时间格式字符串 */
fputs("\nEnter format string(^D or 'quit' to exit): ",
stdout);
if (!fgets(reqBuf, sizeof reqBuf, stdin)) {
printf("\n");
break; /* EOF */
}
/*
* 为日期时间请求字符串添加NULL字符串作为结尾,另外同时去掉末尾的换行符
*/
z = strlen(reqBuf);
if (z > 0 && reqBuf[--z] == '\n')
reqBuf[z] = 0;
if (z == 0) /*客户端进输入了enter */
continue;
/*
* 输入 quit 退出
*/
if (!strcasecmp(reqBuf, "QUIT")) {
printf("press any key to end client.\n");
getchar();
break;
}
/*
* 发送日期时间请求字符串到服务器,注意请求信息中去掉了NULL字符
*/
z = write(sockfd, reqBuf, strlen(reqBuf));
printf("client has sent ??%s?? to the sever\n", reqBuf);
if (z < 0)
bail("write()");
/*
* 从客户端套接字中读取服务器发回的应答
*/
if ((nbytes = read(sockfd, buf, sizeof buf)) == -1) {
fprintf(stderr, "Read Error: %s\n",
strerror(errno));
exit(1);
}
/*
* 若服务器由于某一种原因关闭了链接,则客户段需要处理此事件
*/
if (nbytes == 0) { /* ????EOF */
printf("server has closed the socket.\n");
printf("press any key to exit...\n");
getchar();
break;
}
buf[nbytes] = '\0';
/*
* 输出日期时间结果
*/
printf("result from %s port %u :\n\t'%s'\n",
inet_ntoa(server_addr.sin_addr),
(unsigned)ntohs(server_addr.sin_port),
buf);
}
close(sockfd);
return 0;
}
(3)执行程序