1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 13 #define SERV_PORT 9999 14 15 16 17 //信号捕捉函数 回收子进程 18 void catch_child(int signum) 19 { 20 while(waitpid(0, NULL, WNOHANG) > 0); 21 return; 22 } 23 24 //scoket多进程并发 25 int main() 26 { 27 int lfd, cfd; 28 pid_t pid; 29 char buf[BUFSIZ]; 30 31 struct sockaddr_in serv_addr, clit_addr; 32 33 //初始化sockaddr结构体 34 bzero(&serv_addr, sizeof(serv_addr)); //地址结构清零 35 serv_addr.sin_family = AF_INET; 36 serv_addr.sin_port = htons(SERV_PORT); 37 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 38 39 socklen_t addr_len, clit_addr_len; 40 41 lfd = socket(AF_INET, SOCK_STREAM, 0); 42 if (lfd == -1){ 43 perror("socket error"); 44 exit(1); 45 } 46 47 addr_len = sizeof(serv_addr); 48 int ret = bind(lfd, (const struct sockaddr *)&serv_addr, addr_len); 49 if (ret == -1){ 50 perror("bind error"); 51 exit(1); 52 } 53 54 ret = listen(lfd, 128); 55 if (ret == -1){ 56 perror("listen error"); 57 exit(1); 58 } 59 60 clit_addr_len = sizeof(clit_addr); 61 int i; 62 while(1){ 63 cfd = accept(lfd, (struct sockaddr *)&clit_addr, &clit_addr_len); 64 if (cfd == -1){ 65 perror("accept error"); 66 exit(1); 67 } 68 69 //创建子进程 70 pid = fork(); 71 if (pid < 0){ 72 perror("fork error"); 73 exit(1); 74 } else if (pid == 0){ //子进程 75 close(lfd); //子进程负责连接客户端,所以关闭用于监听的文件描述符 76 for (; ;){ //不断循环,可以一直输入 77 ret = read(cfd, buf, sizeof(buf)); 78 if (ret == -1){ 79 perror("read error"); 80 exit(1); 81 } else if (ret == 0){ 82 close(cfd); 83 exit(1); 84 } 85 ret = write(STDOUT_FILENO, buf, ret); 86 if (ret == -1){ 87 perror("write error"); 88 exit(1); 89 } 90 for(i = 0; i < ret; i ++){ 91 buf[i] = toupper(buf[i]); 92 } 93 write(cfd, buf, ret); 94 write(STDOUT_FILENO, buf, ret); 95 } 96 } else { //父进程注册信号捕捉函数,不断回收子进程,防止僵尸进程的出现 97 struct sigaction act; 98 act.sa_handler = catch_child; 99 sigemptyset(&act.sa_mask); 100 act.sa_flags = 0; 101 ret = sigaction(SIGCHLD, &act, NULL); 102 if (ret != 0){ 103 perror("sigaction error"); 104 exit(1); 105 } 106 close(cfd); //父进程用于监听,所以关闭连接用的文件描述符 107 continue; 108 } 109 } 110 }



