您的位置:首页 > 其它

高级I/O---多路复用---poll

2016-06-01 12:23 471 查看
稍加改进的多路复用--pollpoll是一个在select上稍加改进的多路复用版本,不久后就被功能完善的epoll所取代,它与select的区别在于select的返回通过输入参数来返回,这样每次都要添加要关心的文件描述符到其文件描述符集中,而poll设置了一个结构体指针参数,通过他就可以知道状态变化,但免不了的是依旧需要遍历整个buf,它的大小可以由用户自定义,但是过于大的集合会使得服务器负担大大加重,而太小的集合又因为大多的socket都在等待数据到来,效率上又会下滑很多,所以poll很尴尬。

poll的函数
#include <poll.h>

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

struct pollfd {
int   fd;         /* file descriptor */
short events;     /* requested events */
short revents;    /* returned events */
};
poll的函数与select不一样的地方就是它的fds参数,他是一个结构体指针,结构体的定义就是下面那个
struct pollfd,其中的events是设置的时候所要关心的时间,revents是输出当大于零的时候便说明发生了event所设置的情况,revents不用手动清空,他会自动清空。

因为和select差不多,就直接看代码吧
下面是实现的一个简单的poll版本的tcp服务器

因为前面的设置监听套接字和之前的都一样就忽略了
43 void PollServer(int sock)
44 {
45     int i=0;
46     int max_fd=-1;
47     struct pollfd fds[_MAX_FDS_];
48     for(;i<_MAX_FDS_;i++)
49     {
50         fds[i].fd=-1;
51     }
52     fds[0].fd=sock;
53     max_fd=sock;
54     fds[0].events=POLLIN; //设置为所关心的事件
55     int timeout;
56     while(1)
57     {
58         int new_sock=-1;
59
60         struct sockaddr_in client;
61         socklen_t client_len=sizeof(client);
62
63         fds[0].fd=sock;
64         fds[0].events=POLLIN;
65         timeout=5000;
66         switch(poll(fds,max_fd+1,timeout))//依然需要循环
67         {
68             case -1:
69                 perror("poll");
70                 continue;
71             case 0:
72                 printf("timeout\n");
73                 continue;
74             default:
75                 {
76                     for(i=0;i<_MAX_FDS_;i++)
77                     {
78                         int fd=fds[i].fd;
79                         if(fd==sock&&fds[i].revents>0)
//当有新的连接时
80                         {
81                     new_sock=accept(sock,(struct sockaddr*)\
82                                                                                                         &client,&client_len);
83                             printf("%d\n",new_sock);
84                             for(i=0;i<_MAX_FDS_;i++)
85                             {
86                                 if(fds[i].fd<0)
87                                 {
88                               fds[i].fd=new_sock;
89                               fds[i].events=POLLIN;
90                                     break;
91                                 }
92                             }
93                             if(i==_MAX_FDS_)
94                             {
95                                 close(new_sock);
96                             }
97                         }
98                         else if(fd>0&&fds[i].revents>0)
//当有需要读的数据时
99                         {
100                             char buf[1024];
101                            memset(buf,'\0',sizeof(buf));
102                      ssize_t size=read(fd,buf,sizeof(buf)-1);
103                             if(size>0)
104                             {
105                                 buf[size]='\0';
106                             printf("client::%s\n",buf);
107                             }else if(size==0){
108                                 close(fd);
109                                 fds[i].fd=-1;
110                                 fds[i].events=-1;
111                             }else{
112                                 perror("read");
113                                 continue;
114                             }
115                         }
116                     }
117                 }
118             }
119         }
120 }
121

poll和select的区别并不大,所以很快被epoll淘汰掉了
本文出自 “痕迹” 博客,请务必保留此出处http://wpfbcr.blog.51cto.com/10696766/1785118
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: