在前面的回射服务器中,无法处理多个客户端的连接,原因在于线程中,有一个死循环一直接收客户端发送的消息,accept函数没有机会从listen维护的就绪队列头中获取新的连接。
处理办法:将accept置于一个死循环中不断接收新的连接,当接收新的连接后,开辟一个新的进程,在新进程中处理和客户端的通信。
服务端代码如下:
1 #include<stdio.h> 2 #include <sys/types.h> /* See NOTES */ 3 #include <sys/socket.h> 4 #include <netinet/ip.h> 5 #include <errno.h> 6 #include <stdlib.h> 7 #include <netinet/in.h> 8 #include <arpa/inet.h> 9 #include <unistd.h> 10 #include <string.h> 11 void do_service(int conn){ 12 13 char recvbuffer[1024]; 14 while(1){ 15 memset(recvbuffer,0,sizeof(recvbuffer)); 16 read(conn,&recvbuffer,sizeof(recvbuffer)); 17 fputs(recvbuffer,stdout); 18 write(conn,recvbuffer,strlen(recvbuffer)); 19 } 20 } 21 int main(){ 22 int socketfd; 23 socketfd=socket(PF_INET,SOCK_STREAM,0); 24 if(socketfd<0){ 25 perror("socket"); 26 exit(EXIT_FAILURE); 27 } 28 29 struct sockaddr_in sockaddress; 30 sockaddress.sin_family=AF_INET; 31 sockaddress.sin_port=htons(5188); 32 sockaddress.sin_addr.s_addr=htonl(INADDR_ANY);//INADDR_ANY接收任何地址的连接 33 //sockaddress.sin_addr.s_addr=inet_addr("127.0.0.1");//也可以是这种方式 34 35 int on=1; 36 if (setsockopt(socketfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))<0){ 37 perror("setsockopt"); 38 exit(EXIT_FAILURE); 39 } 40 41 if(bind(socketfd,(struct sockaddr*)&sockaddress,sizeof(sockaddress))<0){ 42 perror("bind"); 43 exit(EXIT_FAILURE); 44 } 45 46 if ( listen(socketfd,SOMAXCONN)<0){ 47 perror("listen"); 48 exit(EXIT_FAILURE); 49 } 50 51 int conn; 52 struct sockaddr_in peeraddr; 53 socklen_t len=sizeof(struct sockaddr_in); 54 pid_t pid; 55 while(1){ 56 conn=accept(socketfd,(struct sockaddr*)&peeraddr,&len); 57 if (conn<0){ 58 perror("accept"); 59 exit(EXIT_FAILURE); 60 } 61 printf("client ip:%s port:%d\n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port)); 62 pid=fork(); 63 if (pid<0){//开启进程失败 64 perror("fork"); 65 exit(EXIT_FAILURE); 66 }else if(pid==0){//进入子进程处理过程 67 close(socketfd); 68 do_service(conn); 69 }else{//主进程处理过程 70 close(conn);//主进程执行到这后就不需要连接套接字了,关闭它 71 } 72 } 73 return 0; 74 75 }