select实现io复用

select实现tcp并发服务器(还没有实现完成)

 20 #include <sys/un.h>
 21 #define PORT 8888
 22 #define IP "192.168.126.52"
 23 int main(int argc, const char *argv[])
 24 {
 25     //1:获取网络通信端点
 26     int sfd=socket(AF_INET,SOCK_STREAM,0);
 27     if(sfd==-1)
 28     {
 29         perror("socket error");
 30         return -1;
 31     }
 32     printf("socket success,sfd=%d\n",sfd);
 33 
 34     //2:绑定ip 端口号
 35     struct sockaddr_in sin;
 36     sin.sin_family=AF_INET;
 37     sin.sin_port=htons(PORT);
 38     sin.sin_addr.s_addr=inet_addr(IP);
 39     if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
 40     {
 41         perror("bind error");
 42         return -1;
 43     }
 44     printf("bind success\n");
 45 
 46     //3:将套接字设置成被动监听状态
 47     if(listen(sfd,128)==-1)
 48     {
 49         perror("listen error");
 50         return -1;
 51     }
 52     printf("listen success\n");
 53 
 54     //4:阻塞等待客户端连接
 55     //定义接收客户端信息容器
 56     struct sockaddr_in cin;
 57     socklen_t addrlen=sizeof(cin);
 58     int newfd=-1;//新建用于通信的套接字文件
 59     char rbuf[128]="";//键盘上输入数据
 60 
 61     //11:创建fd_set类型的变量,作为文件描述符容器
 62     fd_set readfds,tempfds;
 63     //12:清空容器
 64     FD_ZERO(&readfds);
 65     //13:将SFD和0号文件描述符放入
 66     FD_SET(sfd,&readfds);
 67     FD_SET(0,&readfds);
 68 
 69     //随着客户端newfd的产生,sfd不在是集合中的文件描述符的最大值
 70     int maxfd=sfd;//存放容器中最大文件描述符的最大值
 71 
 72     while(1)//对多个客户端处理,加上循环
 73     {
 74         tempfds=readfds;//将容器复制一份,因为select函数会删除容器中未触发事件的文件描述符
 75         //阻塞等待集合中事件产生
 76         int res=select(maxfd+1,&tempfds,0,0,0);
 77         if(res==0)
 78         {
 79             printf("timeout\n");
 80             return -1;
 81         }
 82         else if(res==-1)
 83         {
 84             perror("select error");
 85             return -1;
 86         }
 87 
 88         //如果程序执行到此,说明select集合中有事件发生
 89         //接下来判断哪个文件描述符发生了事件,发生了事件的文件描述符会留下,其他删除
 90     if(FD_ISSET(sfd,&tempfds))  //如果sfd在集合中,说明sfd执行了事件解除了阻塞
 91     {
 92         newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen);
 93         if(newfd==-1)
 94         {
 95             perror("accept error");
 96             return -1;
 97         }
 98         printf("newfd=%d,新用户上线,ip地址为%s,端口号为%d\n",newfd,inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
 99 
100 
101         //将客户端文件描述符放入集合中
102         FD_SET(newfd,&readfds);
103         //当有新的文件描述符加入到集合中,更新文件描述符的最大值
104         if(newfd>maxfd)
105         {
106             maxfd=newfd;
107         }
108     }
109 
110 
111     if(FD_ISSET(0,&tempfds))//如果0号描述符在集合中,说明0号描述符执行了事件
112     {
113         //键盘上输入事件
114         fgets(rbuf,sizeof(rbuf),stdin);
115         rbuf[strlen(rbuf)-1]=0;
116         printf("触发了键盘输入事件:%s\n",rbuf);
117     }
118 
119     if(FD_ISSET(newfd,&tempfds))//如果newfd在集合中说明客户端执行了事件,执行客户端的代码
120     {
121 
122 /*  FD_SET(0,&readfds);//事件出发后会删除未触发事件的文件描述符,所以最后添加,但是比较麻烦不用
123     FD_SET(sfd,&readfds); //解决方法是复制一份容器*/
124 
125         //5:与客户端进行通信
126         char rbuf[128]="";
127         //while(1) 不需要循环了,循环会导致键盘任务无法触发
128         //{
129             bzero(rbuf,sizeof(rbuf));
130             int res=recv(newfd,rbuf,sizeof(rbuf),0);
131             if(res==0)
132             {
133                 printf("对方已下线\n");
134             //  break;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
135                 close(newfd);//关闭套接字
136                 continue;//退出进行下一轮while循环会导致键盘任务无法触发
137 
138                 //将当前关闭的文件描述从readfd集合中移除
139                 FD_CLR(newfd,&readfds);
140                 //更新maxfd
141 
142             }
143             printf("[%s:%d]:%s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),rbuf);
144             strcat(rbuf,"<<<>>>");
145             send(newfd,rbuf,sizeof(rbuf),0);
146             printf("sned success\n");
147     //  }
148 
149     }
150     }
151     close(sfd);
152 
153     return 0;
154 }
~                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
~                

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值