[转]poll技术
poll()函数:这个函数是某些Unix系统提供的用于执行与select()函数同等功能的函数,下面是这个函数的声明:
#include <poll.h>
int poll(struct pollfd fds[], nfds_t nfds, int timeout);
参数说明:
fds:是一个struct
pollfd结构类型的数组,用于存放需要检测其状态的Socket描述符;每当调用这个函数之后,系统不会清空这个数组,操作起来比较方便;特别是对于
socket连接比较多的情况下,在一定程度上可以提高处理的效率;这一点与select()函数不同,调用select()函数之后,select()
函数会清空它所检测的socket描述符集合,导致每次调用select()之前都必须把socket描述符重新加入到待检测的集合中;因
此,select()函数适合于只检测一个socket描述符的情况,而poll()函数适合于大量socket描述符的情况;
nfds:nfds_t类型的参数,用于标记数组fds中的结构体元素的总数量;
timeout:是poll函数调用阻塞的时间,单位:毫秒;
返回值:
>0:数组fds中准备好读、写或出错状态的那些socket描述符的总数量;
==0:数组fds中没有任何socket描述符准备好读、写,或出错;此时poll超时,超时时间是timeout毫秒;换句话说,如果所检测的
socket描述符上没有任何事件发生的话,那么poll()函数会阻塞timeout所指定的毫秒时间长度之后返回,如果timeout==0,那么
poll() 函数立即返回而不阻塞,如果timeout==INFTIM,那么poll()
函数会一直阻塞下去,直到所检测的socket描述符上的感兴趣的事件发生是才返回,如果感兴趣的事件永远不发生,那么poll()就会永远阻塞下去;
-1: poll函数调用失败,同时会自动设置全局变量errno;
如果待检测的socket描述符为负值,则对这个描述符的检测就会被忽略,也就是不会对成员变量events进行检测,在events上注册的事件也会被忽略,poll()函数返回的时候,会把成员变量revents设置为0,表示没有事件发生;
另外,poll()
函数不会受到socket描述符上的O_NDELAY标记和O_NONBLOCK标记的影响和制约,也就是说,不管socket是阻塞的还是非阻塞
的,poll()函数都不会收到影响;而select()函数则不同,select()函数会受到O_NDELAY标记和O_NONBLOCK标记的影
响,如果socket是阻塞的socket,则调用select()跟不调用select()时的效果是一样的,socket仍然是阻塞式TCP通讯,相
反,如果socket是非阻塞的socket,那么调用select()时就可以实现非阻塞式TCP通讯;
所以poll() 函数的功能和返回值的含义与 select()
函数的功能和返回值的含义是完全一样的,两者之间的差别就是内部实现方式不一样,select()函数基本上可以在所有支持文件描述符操作的系统平台上运
行(如:Linux 、Unix
、Windows、MacOS等),可移植性好,而poll()函数则只有个别的的操作系统提供支持(如:SunOS、Solaris、AIX、HP提供
支持,但是Linux不提供支持),可移植性差;
strust pollfd结构说明:
typedef struct pollfd {
int fd; /* 需要被检测或选择的文件描述符*/
short events; /* 对文件描述符fd上感兴趣的事件 */
short revents; /* 文件描述符fd上当前实际发生的事件*/
} pollfd_t;
typedef unsigned long nfds_t;
经常检测的事件标记: POLLIN/POLLRDNORM(可读)、POLLOUT/POLLWRNORM(可写)、POLLERR(出错)
如果是对一个描述符上的多个事件感兴趣的话,可以把这些常量标记之间进行按位或运算就可以了;
比如:对socket描述符fd上的读、写、异常事件感兴趣,就可以这样做:struct pollfd fds;
fds[nIndex].events=POLLIN | POLLOUT | POLLERR;
当 poll()函数返回时,要判断所检测的socket描述符上发生的事件,可以这样做: struct pollfd fds;
检测可读TCP连接请求:
if((fds[nIndex].revents & POLLIN) == POLLIN){//接收数据/调用accept()接收连接请求}
检测可写:
if((fds[nIndex].revents & POLLOUT) == POLLOUT){//发送数据}
检测异常:
if((fds[nIndex].revents & POLLERR) == POLLERR){//异常处理}
------------------------------------------------------------------------------------------------------------
// 【poll实例】
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <poll.h>
#define MAX_BUFFER_SIZE 1024 /* 缓冲区大小*/
#define IN_FILES 3 /* 多路复用输入文件数目*/
#define TIME_DELAY 6000 /* 超时时间秒数 */
#define MAX(a, b) ((a > b)?(a):(b))
int main(void)
{
struct pollfd fds[IN_FILES];
char buf[MAX_BUFFER_SIZE];
int i, res, real_read, maxfd;
/*首先按一定的权限打开两个源文件*/
fds[0].fd = 0;
if((fds[1].fd = open ("in1", O_RDONLY|O_NONBLOCK)) < 0)
{
printf("Open in1 error\n");
return 1;
}
if((fds[2].fd = open ("in2", O_RDONLY|O_NONBLOCK)) < 0)
{
printf("Open in2 error\n");
return 1;
}
/*取出两个文件描述符中的较大者*/
for (i = 0; i < IN_FILES; i++)
{
fds.events = POLLIN;
}
while(fds[0].events || fds[1].events || fds[2].events)
{
if (poll(fds, IN_FILES, TIME_DELAY) <= 0)
{
printf("poll error\n");
return 1;
}
for (i = 0; i< IN_FILES; i++)
{
if (fds.revents)
{
memset(buf, 0, MAX_BUFFER_SIZE);
real_read = read(fds.fd, buf, MAX_BUFFER_SIZE);
if (real_read < 0)
{
if (errno != EAGAIN)
{
return 1;
}
}
else if (!real_read)
{
close(fds.fd);
fds.events = 0;
}
else
{
if (i == 0)
{
if ((buf[0] == 'q') || (buf[0] == 'Q'))
{
return 1;
}
}
else
{
buf[real_read] = '\0';
printf("%s", buf);
}
} /* end of if real_read*/
} /* end of if revents */
} /* end of for */
} /*end of while */
exit(0);
}
[转]poll技术的更多相关文章
- 基本套接字编程(4) -- poll篇
1. poll技术 poll函数起源于SVR3,最初局限于流设备.SVR4取消了这种限制,允许poll工作在任何描述符上.poll提供的功能与select类似,不过在处理流设备时,它能够提供额外的信息 ...
- Linux Network IO Model、Socket IO Model - select、poll、epoll
目录 . 引言 . IO机制简介 . 阻塞式IO模型(blocking IO model) . 非阻塞式IO模型(noblocking IO model) . IO复用式IO模型(IO multipl ...
- select, poll, epoll的实现分析
select, poll, epoll都是Linux上的IO多路复用机制.知其然知其所以然,为了更好地理解其底层实现,这几天我阅读了这三个系统调用的源码. 以下源代码摘自Linux4.4.0内核. 预 ...
- select、poll、epoll
1.概念 select.poll.epoll都是事件触发机制,当等待的事件发生就触发进行处理,用于I/O复用 2.简单例子理解 3.select函数 3.1函数详解 int select(int ma ...
- (转)Linux Network IO Model、Socket IO Model - select、poll、epoll
Linux Network IO Model.Socket IO Model - select.poll.epoll 原文:https://www.cnblogs.com/LittleHann/p/ ...
- 高级IO复用应用:聊天室程序
简单的聊天室程序:客户端从标准输入输入数据后发送给服务端,服务端将用户发送来的数据转发给其它用户.这里采用IO复用poll技术.客户端采用了splice零拷贝.服务端采用了空间换时间(分配超大的用户数 ...
- epoll全面讲解:从实现到应用
多路复用的适用场合 • 当客户处理多个描述符时(例如同时处理交互式输入和网络套接口),必须使用I/O复用. • 如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,一般也要用 ...
- epoll源码分析(转)
在create后会创建eventpoll对象保存在一个匿名fd的file struct的private指针中,然后进程睡在等待队列上面. 对于等待的fd,通过poll机制在准备好之后会调用相应的cal ...
- webSocket的 原理 及 实现
websocket协议是基于Tcp的一种新的网络协议,它实现了客户端与服务器的双向通行,并允许服务端主动发送信息给客户端.WebSocket是html5中的协议. Http协议与WebSocket协议 ...
随机推荐
- 对比AMD 890、AMD 880、 AMD 790、AMD 785、 AMD 780、AMD 7
770无集显.中低端独显主流. 780G带集显.现在可以无视. 785G现在是带集显的主流. 790GX高端带集显. 790FX专高端,无集显. 790X带集显.基本无视. 870 大板,无集显 88 ...
- TCP三次握手及四次挥手详细图解(未完)
TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接: (完成三次握手,客户端与服务器开始传送数据) 所谓三次握手(Three-way Handshake),是指建立一 ...
- HDU 5927 Auxiliary Set (dfs)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5927 题意: 给你一棵树,其中有一些'不重要'的点,要是这些'不重要'的点的子树中有两个重要的点的LC ...
- POJ 3298 Antimonotonicity (思维)
题目链接:http://poj.org/problem?id=3298 找一个最长不要求连续的子序列,如a1 > a3 < a6 > a7 ... 举个例子模拟一下差不多明白了,a[ ...
- JAVA大数运算
java大数是个好东西,用起来方便,代码短. 代码如下: import java.util.*; import java.math.*; public class Main { public stat ...
- LeetCode 刷题记录
写在前面:因为要准备面试,开始了在[LeetCode]上刷题的历程.LeetCode上一共有大约150道题目,本文记录我在<http://oj.leetcode.com>上AC的所有题目, ...
- Web Service实现分布式服务的基本原理
简单的说, 就是客户端根据WSDL 生成 SOAP 的请求消息, 通过 HTTP 传输方式(也可以是其它传输方式, 如 FTP 或STMP 等,目前 HTTP 传输方式已经成为 J2EE Web Se ...
- Js中获取frames中的元素
var oCombo = window.parent.frames["frmresourcetype"].document.getElementById('cmbType') ; ...
- Gulp 学习总结
Gulp 自动化工具开发非常方便,便于上手,值得使用. 一.Gulp安装 gulp是基于NodeJS运行的,所以需要想安装NodeJS. http://nodejs.org/download/ 安装 ...
- MFC中关于子对话框中编辑框不能编辑的问题
最近在用MFC写程序.发现子对话框中的编辑框不能编辑.具体问题是这样的: 我有一个对话框YhglDlg,创建了这个对话框的子对话框ZjyhxxDlg,子对话框的Style属性为Child,Border ...