(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)执行程序
时间: 2024-12-28 10:23:40