用多线程实现回射客户端程序
int pthread_detach(pthread_t thread);
客户端不变:
1 #include<unistd.h> 2 #include<sys/types.h> 3 #include<sys/socket.h> 4 #include<string.h> 5 #include<stdlib.h> 6 #include<stdio.h> 7 #include<errno.h> 8 #include<netinet/in.h> 9 #include<arpa/inet.h> 10 #define ERR_EXIT(m) 11 do 12 { 13 perror(m); 14 exit(EXIT_FAILURE); 15 }while(0) 16 int main(void) 17 { 18 int sock;//客户端创建套接字 19 if((sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0) 20 ERR_EXIT("socket error"); 21 22 struct sockaddr_in servaddr;//本地协议地址赋给一个套接字 23 memset(&servaddr,0,sizeof(servaddr)); 24 servaddr.sin_family=AF_INET; 25 servaddr.sin_port=htons(5188); 26 27 servaddr.sin_addr.s_addr=inet_addr("127.0.0.1");//服务器段地址 28 //inet_aton("127.0.0.1",&servaddr.sin_addr); 29 30 if(connect(sock,(struct sockaddr*)&servaddr,sizeof(servaddr))<0) 31 ERR_EXIT("connect"); 32 char sendbuf[1024]={0}; 33 char recvbuf[1024]={0}; 34 while(fgets(sendbuf,sizeof(sendbuf),stdin)!=NULL)//默认有换行符 35 { 36 write(sock,sendbuf,strlen(sendbuf)); 37 read(sock,recvbuf,sizeof(recvbuf)); 38 fputs(recvbuf,stdout); 39 40 memset(sendbuf,0,sizeof(sendbuf)); 41 memset(recvbuf,0,sizeof(recvbuf)); 42 } 43 close(sock); 44 45 return 0; 46 }
服务器端当有新连接到来的时候,新建一个线程,并且在这个线程的入口函数中来处理连接:
1 #include<unistd.h> 2 #include<sys/types.h> 3 #include<sys/socket.h> 4 #include<netinet/in.h> 5 #include<arpa/inet.h> 6 #include<stdlib.h> 7 #include<stdio.h> 8 #include<errno.h> 9 #include<string.h> 10 #include<pthread.h> 11 #define ERR_EXIT(m) 12 do 13 { 14 perror(m); 15 exit(EXIT_FAILURE); 16 }while(0) 17 18 void echo_srv(int conn) 19 { 20 char recvbuf[1024]; 21 while(1) 22 { 23 memset(recvbuf,0,sizeof(recvbuf)); 24 int ret=read(conn,recvbuf,sizeof(recvbuf)); 25 if(ret==0) 26 { 27 printf("client close "); 28 break; 29 } 30 else if(ret==-1) 31 { 32 ERR_EXIT("read"); 33 } 34 fputs(recvbuf,stdout); 35 write(conn,recvbuf,ret); 36 } 37 38 } 39 void* thread_routine(void* arg) 40 { 41 //当前新线程设置为分离状态,防止僵死 42 pthread_detach(pthread_self()); 43 //int conn=(int)arg; 44 int conn=*(int*)arg; 45 free(arg); 46 echo_srv(conn); 47 printf("exiting thread... "); 48 return NULL; 49 } 50 int main(void) 51 { 52 int listenfd; 53 if((listenfd=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0) 54 ERR_EXIT("socket"); 55 struct sockaddr_in servaddr; 56 memset(&servaddr,0,sizeof(servaddr)); 57 servaddr.sin_family=AF_INET; 58 servaddr.sin_port=htons(5188); 59 servaddr.sin_addr.s_addr=htonl(INADDR_ANY); 60 61 int on=1; 62 if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))<0) 63 ERR_EXIT("setsockopt"); 64 65 if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0) 66 ERR_EXIT("bind"); 67 if(listen(listenfd,SOMAXCONN)<0) 68 ERR_EXIT("listen"); 69 70 struct sockaddr_in peeraddr; 71 socklen_t peerlen=sizeof(peeraddr); 72 int conn; 73 while(1) 74 { 75 if((conn=accept(listenfd,(struct sockaddr*)&peeraddr,&peerlen))<0) 76 ERR_EXIT("accept"); 77 printf("ip=%s port=%d ",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port)); 78 pthread_t tid; 79 int ret; 80 //不传递(void*)&conn的原因,有新的连接的话conn发生改变,如过新的线程没有把conn取走的话,conn就改变了 81 //较好的方案 82 int * p=malloc(sizeof(int)); 83 *p=conn; 84 ret=pthread_create(&tid,NULL,thread_routine,(void*)p); 85 //ret=pthread_create(&tid,NULL,thread_routine,(void*)conn); 86 87 if(ret!=0) 88 { 89 fprintf(stderr,"pthread_create%s ",strerror(ret)); 90 exit(EXIT_FAILURE); 91 } 92 93 } 94 return 0; 95 }