尝试了一下在主进程只fork,子进程accept的结构,由于是测试用的小例子所以限定了用户数量为5个。
1 #include <unistd.h> 2 #include <pthread.h> 3 #include <sys/wait.h> 4 #include <sys/socket.h> 5 #include <netinet/in.h> 6 #include <arpa/inet.h> 7 #include <signal.h> 8 #include <errno.h> 9 #include <stdlib.h> 10 #include <stdio.h> 11 #include <string.h> 12 13 #define USERNUM 5 14 #define SERVPORT 4322 15 16 void 17 rep_err(const char *msg) 18 { 19 fprintf(stderr, "%s\n", msg); 20 perror("ECHOSERVER"); 21 exit(-1); 22 } 23 24 25 void 26 dealchild(int signo) 27 { 28 pid_t pid; 29 int stat; 30 while((pid = waitpid(-1, &stat, WNOHANG)) > 0); 31 printf("Process %u is TERMINAL\n", pid); 32 return; 33 } 34 35 void dofork(int); 36 37 pthread_mutex_t MUTEX = PTHREAD_MUTEX_INITIALIZER; 38 39 int 40 main(int argc, char *argv[]) 41 { 42 int listenfd, err, i; 43 pid_t pid; 44 struct sockaddr_in servaddr; 45 46 if(signal(SIGCHLD, dealchild) == SIG_ERR) 47 rep_err("SIGNAL"); 48 49 if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) <= 0) 50 rep_err("SOCKET"); 51 52 memset(&servaddr, 0, sizeof(servaddr)); 53 servaddr.sin_family = AF_INET; 54 servaddr.sin_port = htons(SERVPORT); 55 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 56 57 if((err = bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr))) < 0) 58 rep_err("BIND"); 59 60 if((err = listen(listenfd, 128)) < 0) 61 rep_err("LISTEN"); 62 63 for(i = 0; i < USERNUM; ++i) 64 { 65 if((pid = fork()) == 0) 66 { 67 dofork(listenfd); 68 } 69 else if(pid > 0) 70 {} 71 else 72 rep_err("FORK"); 73 } 74 75 pause(); 76 77 exit(0); 78 } 79 80 void 81 dofork(int fd) 82 { 83 int connfd, n; 84 char buffer[256]; 85 char buf[128]; 86 struct sockaddr_in cli; 87 socklen_t clilen; 88 89 clilen = sizeof(cli); 90 pthread_mutex_lock(&MUTEX); 91 if((connfd = accept(fd, (struct sockaddr *)&cli, &clilen)) <= 0) 92 rep_err("ACCEPT"); 93 pthread_mutex_unlock(&MUTEX); 94 95 snprintf(buffer, 256, 96 "HELLO %s , FROM PORT : %d\n", 97 inet_ntop(AF_INET, &cli.sin_addr, buf, 128), 98 ntohs(cli.sin_port)); 99 100 write(connfd, buffer, strlen(buffer)); 101 102 for(;;) 103 { 104 again: 105 if((n = read(connfd, buffer, 256)) < 0) 106 { 107 if(errno == EINTR) 108 goto again; 109 else 110 rep_err("READ"); 111 } 112 write(connfd, buffer, n); 113 } 114 }