综合unp前五章,写了一个服务器-客户端程序。
主要功能:客户端从标准输入读入字符串发送到服务器,服务器显示。服务器接受连接后,fork()子进程实现具体操作。
服务器主要过程:
socket()->bind()->listen()->accept()->read(),服务器在accept一个clientfd后,fork()一个子进程服务。
客户端:
socket()->connect()->write(),客户端用poll处理服务器socket和标准输入。
测试结果:
(1)新建服务器、客户端
server的父进程处于监听状态,两个子进程和client处于建立连接状态。
(2)传数据,client发送“OFF”表示关闭连接
(3)关闭连接后的端口状态
服务器代码:
1 #include <stdio.h> 2 #include <sys/socket.h> 3 #include <sys/types.h> 4 #include <arpa/inet.h> 5 #include <netinet/in.h> 6 #include <unistd.h> 7 #include <string.h> 8 #include <stdlib.h> 9 #include <sys/wait.h> 10 #include <signal.h> 11 12 void sig_act(int signo) { 13 pid_t pid; 14 while ( (pid = waitpid(-1, 0, WNOHANG)) > 0 ); 15 } 16 17 void foo(struct sockaddr_in addr, int fd) { 18 char buff[1024]; 19 int len; 20 inet_ntop(AF_INET, &addr.sin_addr, buff, sizeof(buff)); 21 printf("connction from %s, port %d\n", buff, ntohs(addr.sin_port)); 22 while(1) { 23 len = read(fd, buff, 1024); 24 if (len > 0) { 25 write(fd, buff, 1024); 26 printf("receive from %d: %s\n", ntohs(addr.sin_port), buff); 27 } 28 else { 29 close(fd); 30 break; 31 } 32 } 33 } 34 int main() { 35 pid_t pid; 36 int serverfd, clientfd; 37 struct sockaddr_in serveraddr, clientaddr; 38 socklen_t clientaddr_len; 39 u_short port = 9999; 40 char buff[1024]; 41 serverfd = socket(AF_INET, SOCK_STREAM, 0); 42 if (serverfd == -1) { 43 printf("socket error\n"); 44 exit(0); 45 } 46 bzero(&serveraddr, sizeof(serveraddr)); 47 serveraddr.sin_family = AF_INET; 48 serveraddr.sin_port = htons(port); 49 serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); 50 if (bind(serverfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1) { 51 printf("bind error\n"); 52 exit(0); 53 } 54 inet_ntop(AF_INET, &serveraddr.sin_addr, buff, sizeof(buff)); 55 printf("server ip is %s running on port %d\n", buff, ntohs(serveraddr.sin_port)); 56 57 if ( listen(serverfd, 1) == -1 ) { 58 printf("listen error\n"); 59 exit(0); 60 } 61 signal(SIGCHLD, sig_act); 62 while(1) { 63 clientaddr_len = sizeof(clientaddr); 64 clientfd = accept(serverfd, (struct sockaddr *)&clientaddr, &clientaddr_len); 65 if ((pid = fork()) == 0) { 66 close(serverfd); 67 foo(clientaddr, clientfd); 68 exit(0); 69 } 70 close(clientfd); 71 } 72 close(serverfd); 73 exit(0); 74 }
客户端代码:
1 #include <stdio.h> 2 #include <sys/socket.h> 3 #include <sys/types.h> 4 #include <arpa/inet.h> 5 #include <netinet/in.h> 6 #include <unistd.h> 7 #include <string.h> 8 #include <stdlib.h> 9 #include <poll.h> 10 11 int main() { 12 int clientfd; 13 struct sockaddr_in clientaddr; 14 char buff[1024]; 15 struct pollfd eventfd[2]; 16 clientfd = socket(AF_INET, SOCK_STREAM, 0); 17 if (clientfd == -1) { 18 printf("socket error\n"); 19 exit(0); 20 } 21 clientaddr.sin_family = AF_INET; 22 clientaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 23 clientaddr.sin_port = htons(9999); 24 if (connect(clientfd, (struct sockaddr *)&clientaddr, sizeof(clientaddr)) == -1) { 25 printf("connet error\n"); 26 exit(0); 27 } 28 eventfd[0].fd = clientfd; 29 eventfd[0].events = POLLRDNORM; 30 eventfd[1].fd = fileno(stdin); 31 eventfd[1].events = POLLRDNORM | POLLWRNORM; 32 int nready; 33 int stdineof = 0; 34 int i; 35 while (1) { 36 nready = poll(eventfd, 2, -1); 37 38 if (eventfd[0].revents & (POLLRDNORM | POLLERR)) { 39 if ( (i = read(clientfd, buff, 1024)) == 0 ) { 40 if (stdineof == 1) 41 break; 42 else { 43 printf("server closed!\n"); 44 eventfd[0].fd = -1; 45 shutdown(clientfd, SHUT_WR); 46 break; 47 } 48 } 49 else { 50 printf("%s\n", buff); 51 } 52 } 53 54 if ( eventfd[1].revents & POLLRDNORM ) { 55 scanf("%s", buff); 56 if (strcmp(buff, "OFF") == 0){ 57 eventfd[1].fd = -1; 58 stdineof = 1; 59 shutdown(clientfd, SHUT_WR); 60 continue; 61 } 62 write(clientfd, buff, 1024); 63 } 64 } 65 close(clientfd); 66 exit(0); 67 }