http://blog.csdn.net/li_ning_/article/details/52167224

poll

一、poll()函数:

这个函数是某些Unix系统提供的用于执行与select()函数同等功能的函数,自认为poll和select大同小异,下面是这个函数的声明:

[cpp] view plain copy
  1. #include <poll.h>
  2. int poll(struct pollfd *fds, nfds_t nfds, int timeout);

参数:

1.第一个参数:一个结构数组,struct pollfd:

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

结构如下:

[cpp] view plain copy
  1. struct pollfd{
  2.  int fd;          //文件描述符
  3.  short events;    //请求的事件
  4.  short revents;   //返回的事件
  5.  };

  events和revents是通过对代表各种事件的标志进行逻辑或运算构建而成的。events包括要监视的事件(就是我需要关注的时间,是读?是写?还是出错?),poll用已经发生的事件填充revents。poll函数通过在revents中设置标志肌肤POLLHUP、POLLERR和POLLNVAL来反映相关条件的存在。不需要在events中对于这些标志符相关的比特位进行设置。如果fd小于0, 则events字段被忽略,而revents被置为0.标准中没有说明如何处理文件结束。文件结束可以通过revents的标识符POLLHUN或返回0字节的常规读操作来传达。即使POLLIN或POLLRDNORM指出还有数据要读,POLLHUP也可能会被设置。因此,应该在错误检验之前处理正常的读操作。

poll函数的事件标志符值:

常量 说明
POLLIN 普通或优先级带数据可读
POLLRDNORM 普通数据可读
POLLRDBAND 优先级带数据可读
POLLPRI 高优先级数据可读
POLLOUT 普通数据可写
POLLWRNORM 普通数据可写
POLLWRBAND 优先级带数据可写
POLLERR 发生错误
POLLHUP 发生挂起
POLLNVAL 描述字不是一个打开的文件

 注意:

1)后三个只能作为描述字的返回结果存储在revents中,而不能作为测试条件用于events中。

  2)第二个参数nfds:要监视的描述符的数目。

  3)最后一个参数timeout:是一个用毫秒表示的时间,是指定poll在返回前没有接收事件时应该等待的时间。如果  它的值为-1,poll就永远都不会超时。如果整数值为32个比特,那么最大的超时周期大约是30分钟。

timeout值 说明
INFTIM 永远等待
0 立即返回,不阻塞进程
>0
等待指定数目的毫秒数

如果是对一个描述符上的多个事件感兴趣的话,可以把这些常量标记之间进行按位或运算就可以了;

比如:

对socket描述符fd上的读、写、异常事件感兴趣,就可以这样做:

[cpp] view plain copy
  1. struct pollfd  fds;
  2. fds[index].events=POLLIN | POLLOUT | POLLERR;

当 poll()函数返回时,要判断所检测的socket描述符上发生的事件,可以这样做:

[cpp] view plain copy
  1. struct pollfd  fds;
  2. //检测可读TCP连接请求:
  3. if((fds[nIndex].revents & POLLIN) == POLLIN)
  4. {
  5. <span style="white-space:pre">    </span>//接收数据,调用accept()接收连接请求
  6. }
  7. //检测可写:
  8. if((fds[nIndex].revents & POLLOUT) == POLLOUT)
  9. {
  10. <span style="white-space:pre">    </span>//发送数据
  11. }
  12. //检测异常:
  13. if((fds[nIndex].revents & POLLERR) == POLLERR)
  14. {
  15. <span style="white-space:pre">    </span>//异常处理
  16. }

二、实例TCP服务器的服务器程序

[cpp] view plain copy
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/socket.h>
  5. #include <sys/types.h>
  6. #include <netinet/in.h>
  7. #include <netdb.h> 
  8. #include <string.h>
  9. #include <errno.h>
  10. #include <poll.h>   //for poll
  11. #define LISTENQ 1024
  12. #define MAXLINE 1024
  13. #define OPEN_MAX 50000
  14. #ifndef INFTIM
  15. #define INFTIM -1
  16. #endif
  17. int start_up(char* ip,int port)  //创建一个套接字,绑定,检测服务器
  18. {
  19. //sock
  20. //1.创建套接字
  21. int sock=socket(AF_INET,SOCK_STREAM,0);
  22. if(sock<0)
  23. {
  24. perror("sock");
  25. exit(0);
  26. }
  27. //2.填充本地 sockaddr_in 结构体(设置本地的IP地址和端口)
  28. struct sockaddr_in local;
  29. local.sin_port=htons(port);
  30. local.sin_family=AF_INET;
  31. local.sin_addr.s_addr=inet_addr(ip);
  32. //3.bind()绑定
  33. if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
  34. {
  35. perror("bind");
  36. exit(1);
  37. }
  38. //4.listen()监听 检测服务器
  39. if(listen(sock,back_log)<0)
  40. {
  41. perror("sock");
  42. exit(1);
  43. }
  44. return sock;    //这样的套接字返回
  45. }
  46. int main(int argc, char *argv[])
  47. {
  48.   int i, maxi, connfd, sockfd;
  49.   int nready;
  50.   ssize_t n;
  51.   socklen_t clilen;
  52.   struct sockaddr_in servaddr;
  53. socklen_t len=sizeof(servaddr);
  54.    char buf[BUFSIZ];
  55. struct pollfd client[OPEN_MAX]; // 用于poll函数第一个参数的数组,存放每次的文件描述符个数
  56.   if( argc != 3 )
  57. {
  58.        printf("Please input %s <hostname>\n", argv[0]);
  59. exit(2);
  60. }
  61. int listenfd=start_up(argv[1],argv[2]);      //创建一个绑定了本地 ip 和端口号的套接字描述符
  62.       client[0].fd = listenfd;         //将数组中的第一个元素设置成监听描述字
  63.       client[0].events = POLLIN;       //将测试条件设置成普通或优先级带数据可读(感兴趣的事件读、写、出错),此处书中为POLLRDNORM,*/
  64. client[0].revents = 0;           //真正发生的事件
  65.       for(i = 1;i < OPEN_MAX; ++i)     //数组中的其它元素将暂时设置成不可用
  66. {
  67. client[i].fd = -1;
  68. }
  69.       maxi = 0;
  70.        while(1)
  71.       {
  72.          nready = poll(client, maxi+1,INFTIM);          //将进程阻塞在poll上
  73.          if( client[0].revents & POLLIN)                //先测试监听描述字
  74.          {
  75. connfd = accept(listenfd,(struct sockaddr*)&servaddr, &clilen);
  76.               for(i = 1; i < OPEN_MAX; ++i)
  77. {
  78. if( client[i].fd < 0 )
  79.                   {
  80.                       client[i].fd = connfd;      //将新连接加入到测试数组中
  81.                      client[i].events = POLLIN;  //POLLRDNORM; 测试条件普通数据可读
  82.                       break;
  83.                   }
  84.                 if( i == OPEN_MAX )
  85.                 {
  86.                         printf("too many clients"); //连接的客户端太多了,都达到最大值了
  87.                     exit(1);
  88.                 }
  89.                 if( i > maxi )
  90.                     maxi = i;        //maxi记录的是数组元素的个数
  91.                 if( --nready <= 0 )
  92.                     continue;            //如果没有可读的描述符了,就重新监听连接
  93. }
  94.           }
  95.           for(i = 1; i <= maxi; i++)  //测试除监听描述字以后的其它连接描述字
  96.           {
  97. if( (sockfd = client[i].fd) < 0) //如果当前描述字不可用,就测试下一个
  98.                   continue;
  99.               if(client[i].revents & (POLLIN | POLLERR))//如果当前描述字返回的是普通数据可读或出错条件
  100.               {
  101.                  if( (n = read(sockfd, buf, MAXLINE)) < 0) //从套接口中读数据
  102.                  {
  103.                       if( errno == ECONNRESET) //如果连接断开,就关闭连接,并设当前描述符不可用
  104.                       {
  105.                          close(sockfd);
  106.                          client[i].fd = -1;
  107.                       }
  108.                       else
  109.                           perror("read error");
  110.                   }
  111.                 else if(n == 0) //如果数据读取完毕,关闭连接,设置当前描述符不可用
  112.                   {
  113.                       close(sockfd);
  114.                       client[i].fd = -1;
  115.                   }
  116.                   else
  117.                       write(sockfd, buf, n); //打印数据
  118.                if(--nready <= 0)
  119.                    break;
  120.               }
  121.           }
  122.      }
  123.      exit(0);
  124.  }

赐教!

I/O多路转接之poll 函数相关推荐

  1. IO多路转接之poll

    IO多路转接之poll 文章目录 IO多路转接之poll 一.Poll 一.Poll 1.函数原型: int poll(struct pollfd *fds, nfds_t nfds, int tim ...

  2. linux网络编程之多路I/O转接服务器poll函数

    (1)poll函数 头文件:#include<poll.h> int  poll(struct  pollfd*fds, nfds_t nfds,int timeout); struct  ...

  3. I/O多路转接之poll——基于TCP协议

    1. 函数 a. 参数: (1)fds:是一个struct pollfd结构类型的指针,指向用于存放需要检测状态的Socket描述符: 每当调用这个函数之后,系统不会清空这个数组,操作起来比较方便:特 ...

  4. I/O多路转接之poll,epoll

    1.poll 函数原型: #include <poll.h> int poll(struct pollfd fds[], nfds_t nfds, int timeout): 参数说明: ...

  5. Linux: I/O多路转接之poll(有图有代码有真相!!!)

    一.poll()函数解析 不同与select使⽤用三个位图来表⽰示三个fdset的⽅方式,poll使⽤用⼀一个 pollfd的指针实现.pollfd结构包含了要监视的event和发⽣生的event, ...

  6. 多路 IO 转接 :poll 函数

    (1)头文件 #include <poll.h> (2)函数原型 int poll (struct pollfd *fds, nfds_t nfds, int timeout); (3)参 ...

  7. IO多路转接 ——— select、poll、epoll

    文章目录 I/O多路转接之select select初识 select函数 socket就绪条件 select基本工作流程 select服务器 select的优点 select的缺点 select的适 ...

  8. select poll epoll 高效IO 多路转接

    目录 五种常见IO模型 高效IO的概念 阻塞 vs 非阻塞 非阻塞IO fcntl函数 I/O多路转接之select 初识select select函数原型 select操作接口 tcp_server ...

  9. 网络编程(三)TCP IO多路转接服务器编程(select)

    同系列文章: 1, 文章目录 一,select知识引入 二,select基本概念 2.1 select概念理解前先总结一下通信过程(便于后文理解select) 2.2 select函数的用法 2.2. ...

最新文章

  1. python单词意思-python 前面几个单词含义
  2. Python的一些小技巧小知识
  3. python 分布式框架_python分布式框架rq的使用
  4. JAVA笔记(十四)
  5. mysql数据库主要用来做什么的_水晶头骨用来做什么的?
  6. 一起来讨论web2.0吧
  7. DOM 节点类型及属性
  8. add()方法和Put()方法的差别
  9. 用 git 维护 vim 代码
  10. 摩拜女程序员状告其前端负责人性骚扰!
  11. MySQL二十四:索引
  12. 华为融合位置服务器,融合服务器
  13. 从“童话脸”到Avatarify,AI换脸究竟带来了什么?
  14. 中国天气预报网接口及城市代码
  15. 如何低成本做好网络营销
  16. 关于知识分享和微软TechEd Roadshow
  17. http 传输原理及格式
  18. 物联网工程毕业设计选题推荐
  19. 一键搭建Ubuntu开发环境
  20. 【小迪安全】web安全|渗透测试|网络安全 | 学习笔记-5

热门文章

  1. java 动态增加定时任务
  2. h.264 去块滤波
  3. 模型和控制器-起步阶段
  4. shouji android输入法,安卓手机主流输入法对比
  5. pymssql mysql_Python利用pymssql访问mysql数据库
  6. 复旦大学计算机学院博士生王斌,复旦大学计算机科学技术学院博士生刘鹏飞荣获...
  7. 分布式是什么意思_机架式ups是什么意思?与分布式DPS有何不同之处?
  8. 测试环境搭建流程_前端构建 DevOps 搭建 DevOps 基础平台(中)
  9. 腾讯吃鸡 android,腾讯吃鸡手游《光荣使命》正式上线:安卓/iOS不限号测试
  10. python矩形填充颜色_在Python中找到所有用0填充的矩形