POLL模型

poll模型

poll模型和select模型差不多,都是通过轮询的方式监听,但是其缺点较多
struct pollfd
{
int fd; //指定要监听的文件描述符
short events; //指定监听fd上的什么事件
short revents; //fd上事件就绪后,用于保存实际发生的事件
};

服务器代码

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<ctype.h>
  5 #include<sys/types.h>
  6 #include<sys/socket.h>
  7 #include<strings.h>
  8 #include<errno.h>
  9 #include<arpa/inet.h>
 10 #include<poll.h>
 11 #define DEFPORT 8000
 12 int main(void)
 13 {
 14     int sfd,cfd;//server文件描述符 client文件描述符
 15     int i,j,nReady,len,datalen;
 16     char buf[1024];//数据
 17     bzero(buf,sizeof(buf));
 18     //网络初始化
 19     struct sockaddr_in server_sock,client_sock;
 20     bzero(&server_sock,sizeof(server_sock));
 21     server_sock.sin_family = AF_INET;
 22     server_sock.sin_port = htons(DEFPORT);
 23     server_sock.sin_addr.s_addr = htonl(INADDR_ANY);
 24     sfd = socket(AF_INET,SOCK_STREAM,0);
 25     bind(sfd,(struct sockaddr*)&server_sock,sizeof(server_sock));
 26     listen(sfd,128);
 27     //poll模型初始化
 28     struct pollfd set[4096];
 29     set[0].fd = sfd;
 30     set[0].events = POLLIN;
 31     for(i=1;i<4096;i++)
 32         set[i].fd = -1;
 33     while(1)
 34     {
 35         nReady = poll(set,4096,-1);//监听集合 最大监听数 阻塞监听 返回监听到
    的数量
 36         while(nReady)//循环,每次处理一个监听事件
 37         {
 38             if(set[0].revents==POLLIN)//判断是否是server读事件
 39             {
 40                 len = sizeof(client_sock);
 41                 cfd = accept(sfd,(struct sockaddr*)&client_sock,&len);//连接
 42                 for(i = 1; i < 4096; i++)//将cfd存入监听集合,并设置监听事件
 43                     if(set[i].fd == -1)
 44                     {
 45                         set[i].fd = cfd;
 46                         set[i].events = POLLIN;
 47                         break;
 48                     }
 49                 if(i==1024)
 50                     perror("client too much\n");
 51                 set[0].revents = 0;//server读事件结束后不再监听
 52             }
 53             else
 54             {
 55                 for(i = 1; i < 4096; i++)//找到对因的recv读事件
 56                 {
 57						if(set[i].fd != -1)
 58                     {
 59                         if(set[i].revents == POLLIN)
 60                         {
 61                             if((datalen = recv(set[i].fd,buf,sizeof(buf),0)>    0))
 62                             {
 63                                 printf("size:%d\n",datalen);
 64                                 for(j = 0; j < datalen; j++)
 65                                     buf[j] = toupper(buf[j]);
 66                                 send(set[i].fd,buf,len,0);
 67                                 bzero(buf,sizeof(buf));
 68                             }
 69                             if(len==0)
 70                             {
 71                                 set[i].revents = 0;
 72                                 close(set[i].fd);
 73                                 set[i].fd = -1;
 74                             }
 75                             set[i].revents = 0;//处理完当前事件后不再处理
 76                             break;
 77							}
 78                     }
 79                 }
 80             }
 81             --nReady;
 82         }
 83     }
 84     return 0;
 85 }

优点

1.不再像select一样需要将传入和传出集合分离,而是通过revent设置
2.可以监听事件的种类更加丰富,例如POLLRDNORM(数据可读)
、POLLERR(发生错误)、POLLHUP (发生挂起)等等
3.监听数量突破1024。

缺点

poll继承了select的几乎所有缺点
1.当轮询数量的增长,轮询监听导致IO处理效率较慢
2.用户必须自己去查找是哪个事件就绪,浪费时间
3.存在大量的无意义的拷贝,浪费资源
4.没有兼容性,无法在windows下使用
5.timeout只能设置到毫秒级别,而select可以达到微秒。

总结

对于第三个优点,poll模型确实可以比select模型监听更多的事件,但是并没有解决实质性的问题。因为在select模型中,1024这个值是因为采用fd_set这个类型导致的,而之所以选择这个类型是因为在监听过程中,select将监听集合中的监听项加入到内核中的IO设备等待队列中,而这个队列采用的是轮询监听的方式,而轮询监听带来的最大问题就是不能及时的处理新的事件请求,必须处理完上一轮所有事件之后,才会处理下一轮的事件,当访问较为频繁时,会出现问题。所以,研究者通过实验,最终确定1024为最优值。因此在poll模型中,单纯的去突破1024并没有什么意义,无法解决问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值