博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
unix下网络编程之I/O复用(三)
阅读量:6693 次
发布时间:2019-06-25

本文共 3670 字,大约阅读时间需要 12 分钟。

poll函数

    在上文中已经介绍了select函数的相关使用,本文将介绍另一个常用的I/O复用函数poll。poll提供的功能与select类似,不过在处理流设备时,它能够提供额外的信息。

poll函数原型:

#include
int poll (struct pollfd * fdarray , unsigned long nfds , int timeout); //返回:就需描述字的个数,0——超时,-1——出错

 第一个参数是指向一个结构数组第一个元素的指针,每个数组元素都是一个pollfd结构。如下:

struct pollfd {	int fd; //descriptor to check	short events; //events of interest on fd`	short revents; //events tha occurred on fd}

要测试的条件由events成员指定,函数在相应的revents成语中返回该描述字的状态。(每个描述字都有两个变量,一个为调用值,另一个为返回结果,从而避免使用值-结果参数,这与select函数是不同的)。下图列出了用于指定events标志以及测试revents标志的一些常值。

上图需要注意的是,POLLERR,POLLHUP,POLLNVAL是处理错误的描述字,因此它们也就不可以出现在input事件中,即events。poll识别三类数据:普通(normal),优先级带(priority band)和高优先级(high priority)。

对TCP和UPD而言,以下条件引起poll返回特定的revents。

1、 All regular TCP data and all UDP data is considered normal.

2、 TCP's out-of-band data (Chapter 24) is considered priority band.
3、 When the read half of a TCP connection is closed (e.g., a FIN is received), this is also considered normal data and a subsequent read operation will return 0.
4、 The presence of an error for a TCP connection can be considered either normal data or an error (POLLERR). In either case, a subsequent read will return –1 with errno set to the appropriate value. This handles conditions such as the receipt of an RST or a timeout.
5、 The availability of a new connection on a listening socket can be considered either normal data or priority data. Most implementations consider this normal data.
6、 The completion of a nonblocking connect is considered to make a socket writable.

                                                                                    ——《unix网络编程》第三版

参数nfds,指示结构数组中元素的个数。

参数timeout:

与select中的timeout不同,poll函数的timeout参数是一int值,表示poll函数返回前等待多长时间,它是毫秒级别的。它有三种情况的取值:1、INFTIM(一个负数值),表示永远等待,即一直阻塞。2、0,表示立即返回,非阻塞。3、>0,表示正待指定数目的毫秒数。

poll函数的返回值:

当poll发生错误时,poll函数的返回值-1,若定时器时间到之前没有任何描述字就绪,则返回0,否则返回就绪描述字的个数,即其revents成员值非0的描述字个数。

如果我们不再关心某个特定描述字,那么可以把与他对应的pollfd结构的fd成员设置成一个负值。poll函数将忽略这样的pollfd结构的events成员,返回时将它的revents成员的值置为0。

 

poll函数的通信列子:一个简单的TCP回射服务器程序

pollServer.c:使用select机制的服务器程序

#include 
#include
#include
#include
#include
#include
/*环境为ubuntu10.04自带c环境,无法自动引入下列宏,所以自己写在前面了*/#define INFTIM -1#define POLLRDNORM 0x040 /* Normal data may be read. */#define POLLRDBAND 0x080 /* Priority data may be read. */#define POLLWRNORM 0x100 /* Writing now will not block. */#define POLLWRBAND 0x200 /* Priority data may be written. */#define MAXLINE 1024#define OPEN_MAX 16 //一些系统会定义这些宏#define SERV_PORT 10001int main(){ int i , maxi ,listenfd , connfd , sockfd ; int nready; int n; char buf[MAXLINE]; socklen_t clilen; struct pollfd client[OPEN_MAX]; struct sockaddr_in cliaddr , servaddr; listenfd = socket(AF_INET , SOCK_STREAM , 0); memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(SERV_PORT); servaddr.sin_addr.s_addr = htonl(INADDR_ANY); bind(listenfd , (struct sockaddr *) & servaddr, sizeof(servaddr)); listen(listenfd,10); client[0].fd = listenfd; client[0].events = POLLRDNORM; for(i=1;i
maxi) maxi = i; nready--; if(nready<=0) continue; } for(i=1;i<=maxi;i++) { if(client[i].fd<0) continue; sockfd = client[i].fd; if(client[i].revents & (POLLRDNORM|POLLERR)) { n = read(client[i].fd,buf,MAXLINE); if(n<=0) { close(client[i].fd); client[i].fd = -1; } else { buf[n]='\0'; printf("Socket %d said : %s\n",sockfd,buf); write(sockfd,buf,n); //Write back to client } nready--; if(nready<=0) break; //no more readable descriptors } } } return 0;}

客户端程序参考上一篇文章。

总结:

   本文介绍了poll函数的原型,参数说明,注意事项以及一个简单的代码例子。在unix后续版本中,加入了epoll函数I/O复用机制,它在一定条件下更加高效,在以后的文章中,会对epoll机制再进行详细的描述。之前在学习python的时候,也接触了select和poll,但是当时了解的比较浅显,希望通过最近的学习可以对unix下I/O复用有更深入的认识。

转载地址:http://tacoo.baihongyu.com/

你可能感兴趣的文章
Python学习教程(Python学习路线):Day15-图像和办公文档处理
查看>>
spring cloud互联网分布式微服务云平台规划分析--spring cloud系统管理平台
查看>>
Just 一个轻量级网络加载库
查看>>
java B2B2C Springboot多租户电子商城系统-spring-cloud-eureka-consumer
查看>>
webpack css提取(简单版)
查看>>
Python3之手动创建迭代器
查看>>
智能穿戴,他让心电监测触手可及
查看>>
java B2B2C Springboot仿淘宝电子商城系统-负载均衡之ribbon+feign
查看>>
大数据为何这么重要?
查看>>
担心过度用电 ,美国纽约州将暂停比特币挖矿18个月
查看>>
kafka详细介绍,安装,配置
查看>>
centos2.8--3.主机添加配置
查看>>
html5 的 details 标记 ,summary标记,布局
查看>>
我的友情链接
查看>>
php memcache
查看>>
lvm管理-扩展
查看>>
Git 如何拆除核弹起爆码,以及 topgit 0.7到0.8的变迁
查看>>
zencart网站怎么隐藏 51la ,cnzz的统计代码图标
查看>>
MacOS X,安装和配置Maven
查看>>
phonegap支持打电话
查看>>