IO多路复用之poll
来源:互联网 发布:3d人体模型软件 编辑:程序博客网 时间:2024/05/17 04:28
poll和select区别:
① poll服务器监视的文件描述符无上限;
② poll将输入、输出参数进行分离。
一、poll函数
函数格式如下所示:
#include <poll.h>int poll ( struct pollfd * fds, unsigned int nfds, int timeout);
不同与select使用三个位图来表示三个fdset的方式,poll使用一个 pollfd的指针实现,即poll将输入、输出参数进行分离。
struct pollfd * fdspollfd 结构体定义如下:struct pollfd { int fd; /* 文件描述符 */ short events; /* 等待的事件 */ short revents; /* 实际发生了的事件 */} ;
每一个pollfd结构体指定了一个被监视的文件描述符,可以传递多个结构体,指示poll()监视多个文件描述符。
每个结构体的events域是监视该文件描述符的事件掩码,由用户来设置这个域。
revents域是文件描述符的操作结果事件掩码,内核在调用返回时设置这个域。
events域中请求的任何事件都可能在revents域中返回。
合法的事件如下:
POLLIN 有数据可读。 POLLRDNORM 有普通数据可读。 POLLRDBAND 有优先数据可读。 POLLPRI 有紧迫数据可读。 POLLOUT 写数据不会导致阻塞。 POLLWRNORM 写普通数据不会导致阻塞。 POLLWRBAND 写优先数据不会导致阻塞。 POLLMSGSIGPOLL 消息可用
此外,revents域中还可能返回下列事件:
POLLER 指定的文件描述符发生错误。 POLLHUP 指定的文件描述符挂起事件。 POLLNVAL 指定的文件描述符非法。
这些事件在events域中无意义,因为它们在合适的时候总是会从revents中返回。
使用poll()和select()不一样,你不需要显式地请求异常情况报告。
POLLIN | POLLPRI等价于select()的读事件.
POLLOUT |POLLWRBAND等价于select()的写事件。
POLLIN等价于POLLRDNORM |POLLRDBAND
而POLLOUT则等价于POLLWRNORM。
例如,要同时监视一个文件描述符是否可读和可写,我们可以设置 events为POLLIN |POLLOUT。在poll返回时,我们可以检查revents中的标志,对应于文件描述符请求的events结构体。如果POLLIN事件被设置,则文件描述符可以被读取而不阻塞。如果POLLOUT被设置,则文件描述符可以写入而不导致阻塞。这些标志并不是互斥的:它们可能被同时设置,表示这个文件描述符的读取和写入操作都会正常返回而不阻塞。
unsigned int nfds, nfds_t类型的参数,用于标记数组fds中的结构体元素的总数量
int timeout timeout参数指定等待的毫秒数,无论I/O是否准备好,poll都会返回。 timeout指定为负数值表示无限超时,使poll()一直挂起直到一个指定事件发生 timeout为0指示poll调用立即返回并列出准备好I/O的文件描述符,但并不等待其它的事件。这种情况下,poll()就像它的名字那样,一旦选举出来,立即返回。
poll( )返回值:
成功时,poll()返回结构体中revents域不为0的文件描述符个数。
如果在超时前没有任何事件发生,poll()返回0。
失败时,poll()返回-1,并设置errno为下列值之一:
EBADF 一个或多个结构体中指定的文件描述符无效。 EFAULTfds 指针指向的地址超出进程的地址空间。 EINTR 请求的事件之前产生一个信号,调用可以重新发起。 EINVALnfds 参数超出PLIMIT_NOFILE值。 ENOMEM 可用内存不足,无法完成请求。
二、代码演示(服务器只读演示)
#include<stdio.h>#include<sys/socket.h>#include<sys/types.h>#include<stdlib.h>#include<netinet/in.h>#include<unistd.h>#include<arpa/inet.h>#include<string.h>#include<poll.h>#define SIZE 100static void usage(const char* proc){ printf("usage:%s [local_ip] [local_port]\n",proc);}int startup(char* ip, int port){ int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock<0) { perror("sock"); exit(1); } struct sockaddr_in local; local.sin_family = AF_INET; local.sin_port = ntohs(port); local.sin_addr.s_addr = inet_addr(ip); if(bind(sock, (struct sockaddr*)&local, sizeof(local)) <0) { perror("bind"); exit(2); } if(listen(sock, 10) <0) { perror("listen"); exit(3); } return sock;}int main(int argc, char* argv[]){ if(argc != 3) { usage(argv[0]); exit(4); } int listen_sock = startup(argv[1], atoi(argv[2])); struct pollfd evs[SIZE]; int i = 0; for(; i<SIZE; i++) { evs[i].fd = -1; evs[i].events = -1; evs[i].revents = -1; } evs[0].fd = listen_sock; evs[0].events = POLLIN; int timeout = 3000; while(1) { switch(poll(evs, SIZE, timeout)) { case 0: // printf("timeout\n"); break; case -1: perror("poll"); break; default: { for(i=0; i<SIZE; i++) { if(i==0 && evs[i].revents == POLLIN) { struct sockaddr_in client; socklen_t len = sizeof(client); int new_sock = accept(listen_sock, (struct sockaddr*)&client, &len); if(new_sock < 0) { perror("accept"); continue; } printf("get a client:%s %d\n", inet_ntoa(client.sin_addr),ntohs(client.sin_port)); int j = 1; for(; j<SIZE; j++) { if(evs[j].fd == -1) { evs[j].fd = new_sock; evs[j].events = POLLIN; break; } } if(j == SIZE) { close(new_sock); continue; } } else if(i != 0 && evs[i].revents == POLLIN) { char buf[1024]; ssize_t ss = read(evs[i].fd, buf, sizeof(buf)-1); if(ss > 0) { buf[ss] = 0; printf("client# %s\n", buf); } else if(ss == 0) { printf("client is quit!\n"); close(evs[i].fd); evs[i].fd = -1; break; } else { perror("read"); close(evs[i].fd); evs[i].fd = -1; continue; } } else// write events { } } } } } return 0;}
poll服务器启动:
用telnet链接测试:
- IO多路复用之poll
- IO多路复用之poll
- IO多路复用之poll
- IO多路复用之poll总结
- IO多路复用之poll总结
- IO多路复用之poll总结
- IO多路复用之poll总结
- IO多路复用之poll总结
- IO多路复用之poll总结
- IO多路复用之poll总结
- IO多路复用之poll总结
- IO多路复用之poll总结
- IO多路复用之poll总结
- IO多路复用之poll总结
- IO多路复用之poll总结
- IO多路复用之poll总结
- IO多路复用之poll总结
- IO多路复用之poll转载
- Opencv 完美配置攻略 2014 (Win8.1 + Opencv 2.4.8 + VS 2013)
- java中用什么方式可以是运行的线程终止????
- CF1 A+B+C
- sqlldr--SQL*Loader的使用
- python Django框架学习
- IO多路复用之poll
- dubbo注册zookeeper时出现未知ip地址url:dubbo://202.106.199.38:20880
- C++学习笔记(五):析构函数
- java 基础
- Ajax页面缓存问题分析与解决办法
- CodeFroces 835C. Star sky(构造题)
- Hive的简介
- L
- linux初步尝试