3.4 多路复用IO解决TCP协议下并发性问题

head.h

 1 #ifndef _HEAD_H_
 2 #define _HEAD_H_
 3 
 4 #include<stdio.h>
 5 #include<stdlib.h>
 6 #include<string.h>
 7 #include<sys/types.h>
 8 #include<sys/socket.h>
 9 #include<arpa/inet.h>
10 #include<netinet/in.h>
11 #include<netinet/ip.h>
12 #include<unistd.h>
13 #include<sys/stat.h>
14 #include<fcntl.h>
15 #include<error.h>
16 #include<errno.h>
17 
18 #define error_exit(_errmsg_) error(EXIT_FAILURE,errno,_errmsg_)
19 #define SER_PORT 50008
20 #define SER_ADDR "192.168.239.129"
21 
22 #endif

Makefile

1 ALL:client server
2 client:client.c
3     gcc $< -o $@
4 server:server.c
5     gcc $< -o $@
6 .PHONY:
7 clean:    rm client server

client.c

 1 //多路复用IO解决TCP协议下并发性问题
 2 #include"head.h"
 3 int main()//client
 4 {
 5     char buff[1024]="hello world!";
 6     char buff0[1024]={0};
 7     char buff1[1024]={0};//buff1与buff可一样,覆盖
 8     char i=1;    
 9 
10     int sockfd=0;
11     struct sockaddr_in seraddr;
12     seraddr.sin_family=AF_INET;
13     seraddr.sin_port=htons(SER_PORT);
14     seraddr.sin_addr.s_addr=inet_addr(SER_ADDR);
15         
16     if(-1==(sockfd=socket(AF_INET,SOCK_STREAM,0)))
17         error_exit("fail to socket!");
18     if(-1==connect(sockfd,(struct sockaddr* )&seraddr,sizeof(seraddr)))
19         error_exit("fail to connect!");
20     //发送
21     while(1)
22     {
23         sprintf(buff0,"%s----%d---",buff,i);
24         //sprintf(buff0,"hello world!---%d---",i);
25         if(-1==send(sockfd,buff0,strlen(buff0)+1,0))
26             error_exit("fail to send!");
27         if(-1==recv(sockfd,buff1,sizeof(buff1),0))//一般客户端中端
28             error_exit("fail to recv!");
29         i++;
30         printf("REPLY:%s\n",buff1);
31         sleep(1);
32     }
33     close(sockfd);
34     return 0;
35 }

server.c

 1 //多路复用IO解决TCP协议下并发性问题
 2 #include"head.h"
 3 int main()//server
 4 {
 5     int confd=0;
 6     int i=0;
 7     char buff[1024]={0};
 8 
 9     fd_set rdfds,tmpfds;//定义读文件描述符集合和备份
10     int maxfd=0;//最大文件描述符+1为nfds
11 
12     int sockfd=0;
13     struct sockaddr_in seraddr,cltaddr;
14     socklen_t addrlen=sizeof(cltaddr);
15     seraddr.sin_family=AF_INET;
16     seraddr.sin_port=htons(SER_PORT);
17     seraddr.sin_addr.s_addr=inet_addr(SER_ADDR);
18     //创建用来通信的文件描述符/为自己申请资源
19     if(-1==(sockfd=socket(AF_INET,SOCK_STREAM,0)))
20         error_exit("fail to socket!");
21     //将文件描述符sockfd和IP地址绑定
22     if(-1==bind(sockfd,(struct sockaddr* )&seraddr,sizeof(seraddr)))
23         error_exit("fail to bind!");
24     //指定链接请求队列的长度
25     if(-1==listen(sockfd,10))
26         error_exit("fail to listen!");
27     //
28     FD_ZERO(&rdfds);
29     FD_SET(sockfd,&rdfds);
30     maxfd=sockfd+1;
31     //maxfd=sockfd;
32     tmpfds=rdfds;//备份
33 
34     while(1)
35     {
36         rdfds=tmpfds;//
37         //监听多个文件描述符集合,一旦有一个来数据后所对应的文件描述符阻塞,其他被剔除
38         select(maxfd,&rdfds,NULL,NULL,NULL);
39         if(FD_ISSET(sockfd,&rdfds))//判断是否有客户端来数据来链接服务器
40         {
41             if(-1==(confd=accept(sockfd,NULL,NULL)))//用confd收取申请链接的客户端的文件描述符/accept阻塞等待功能
42                 error_exit("fail to accept!");
43             FD_SET(confd,&tmpfds);//将接收到的客户端文件描述符加入到文件描述符集合当中
44             maxfd =( maxfd > confd) ? maxfd : (confd+1);//如果有客户端来数据则有文件描述符的值被赋予maxfd
45         }
46         for(i=4;i<maxfd;i++)
47         {
48             if(FD_ISSET(i,&rdfds))
49             {
50                 if(recv(i,buff,sizeof(buff),0)>0)//接收客户端数据
51                 {
52                     getpeername(i,(struct sockaddr*)&cltaddr,&addrlen);
53                     printf("%s:%d-->%s\n",inet_ntoa(cltaddr.sin_addr),ntohs(cltaddr.sin_port),buff);
54                     strcat(buff,"---echo");
55                     if(-1==send(i,buff,strlen(buff)+1,0))//回复客户端
56                         error_exit("fail to send!");
57                 }
58                 else//接收完毕后关闭各confd文件描述符/将文件描述符集合清空
59                 {    close(i);
60                     FD_CLR(i,&tmpfds);
61                 }
62             }
63         }
64     }    
65 
66         close(sockfd);
67         return 0;
68 }

posted @ 2017-03-13 21:51  bkycrmn  阅读(200)  评论(0)    收藏  举报