select poll模式简单分析

来源:互联网 发布:淘宝能申请信用卡吗 编辑:程序博客网 时间:2024/05/20 08:25

通过一个例子来说明select的用法

1:一个非常简单的用法

int main ()
{
        int keyboard;
        int ret,i;
        char c;
        fd_set readfd;
        struct timeval timeout;
        keyboard = open("/dev/tty",O_RDONLY | O_NONBLOCK);
        assert(keyboard>0);
        while(1)
        {
                timeout.tv_sec=1;
                timeout.tv_usec=0;
                FD_ZERO(&readfd);
                FD_SET(keyboard,&readfd);
                ret=select(keyboard+1,&readfd,NULL,NULL,&timeout);
                if(FD_ISSET(keyboard,&readfd))
            {
                      i=read(keyboard,&c,1);
                  if('\n'==c)
                          continue;
                              printf("hehethe input is %c\n",c);
                                                                              
                         if ('q'==c)
                                       break;
            }
        }
   return 0;
}

这里将键盘作为一个文件描述符,用select来它监视键盘文件描述符的变化情况

上述的select只监视文件描述符的读的变化情况,这里用一个fd_set readfd;来装要监视的文件描述符。

setFD_ZERO(&readfd); 将文件描述符readfd集合的所有位设置为0
 FD_SET(keyboard,&readfd); 这条语句是将键盘的文件描述符加到readset里面。

(readset writeset 都是我们指定让内核测试的读写描述字集合)

FD_ISSET(keyboard,&readfd) 判断键盘描述符是否已经准备好读,即已经键入一个字符

这时候就可以将输入的字符打印出来。

 

===========================================================================

下面来说一下select的缺点吧。首先他可以监听的描述符的大小受到FD_SETSIZE大小的限制一般是1024

然后:如果有很多描述符已经准备就绪。我们需要遍历扫描描述符集合,来用FD_ISSET判断某个描述符是否可读或者可写或者异常。这样的如果set增大,那么耗时也将成线性增长。

============================================================================

下面来说一下poll吧:
一下是一段有bug的代码这里仅仅是为了做展示不要深究细节:

      1 #include <stropts.h>
      2 #include <poll.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <iostream>
      6 #include <fcntl.h>
      7
      8 using namespace std;
      9 int main(void)
     10 {
     11 struct pollfd fds[2];
     12 int timeout_msecs = 500;
     13 int ret;
     14 int i;
     15
     16
     17 fds[0].fd = (open("/home/luoli/demo/server.cpp",O_RDWR ));
     18 fds[1].fd = open("/home/luoli/server.cpp",O_RDWR );
     19 fds[0].events = POLLOUT | POLLWRBAND;
     20 fds[1].events = POLLOUT | POLLWRBAND;
     21
     22 //ret = poll(fds, 2, timeout_msecs);
     23 while(1){
     24 ret = poll(fds, 2, timeout_msecs);
     25 if (ret > 0) {
     26    
     27     for (i=0; i<2; i++) {
     28         if (fds[i].revents & POLLWRBAND) {
     29        
     30             printf("some is writing!!\n");
     31         }
     32         if (fds[i].revents & POLLOUT) {
     33        
     34             printf("some is reading!!\n");
     35         }
     36         if (fds[i].revents & POLLHUP) {
     37        
     38             printf("some is hangup!!\n");
     39         }
     40     }
     41 }
     42 }
     43 return 0;
     44 }

fds:是一个struct pollfd结构类型的数组,用于存放需要检测其状态的Socket描述符;每当调用这个函数之后,系统不会清空这个数组,操作起来比较方便;特别是对于socket连接比较多的情况下,在一定程度上可以提高处理的效率;这一点与select()函数不同,调用select()函数之后,select()函数会清空它所检测的socket描述符集合,导致每次调用select()之前都必须把socket描述符重新加入到待检测的集合中;因此,select()函数适合于只检测一个socket描述符的情况,而poll()函数适合于大量socket描述符的情况

看上述两段代码即可看出其区别。

poll() 函数不会受到socket描述符上的O_NDELAY标记和O_NONBLOCK标记的影响和制约,也就是说,不管socket是阻塞的还是非阻塞的,poll()函数都不会收到影响;而select则相反,如果socket是阻塞的socket 那么select的使用与不使用select的效果是一样的

所以poll() 函数的功能和返回值的含义与 select() 函数的功能和返回值的含义是完全一样,但是二者的内部实现是不一样的

strust pollfd结构说明:

typedef struct pollfd {
        int fd;                              
        short events;                  
        short revents;                 
} pollfd_t;

if((fds[nIndex].revents & POLLIN) == POLLIN){//接收数据/调用accept()接收连接请求}


poll的可移植性不如select好。

原创粉丝点击