https://blog.csdn.net/men_wen/article/details/53456474

Linux网络编程—I/O复用模型之poll

1.函数poll

poll系统调用和select类似,也是在指定时间内轮询一定数量的文件描述符,以测试其中是否有就绪者。

#include <poll.h>int poll(struct pollfd *fds, nfds_t nfds, int timeout);
//返回值:若成功,返回就绪的描述符个数,若超时则为0,若出错则为-1
  • fds是指向一个pollfd结构第一个元素的指针。每一个元素都是pollfd结构类型,用于测试某个给定描述符fd的条件
struct pollfd {int   fd;         /* file descriptor */short events;     /* requested events */short revents;    /* returned events */
};

要测试的条件在events中指定,函数相应的revents成员返回该描述符的状态,一个为调用值,一个为返回结果,这与select的传入传出参数不同。 
events和revents可以设置以下常量的一个或多个的按位或结果:

POLLIN      //普通或带外优先数据可读,即POLLRDNORM | POLLRDBAND
POLLRDNORM  //数据可读
POLLRDBAND  //优先级带数据可读
POLLPRI     //高优先级可读数据
POLLOUT     //普通或带外数据可写
POLLWRNORM  //数据可写
POLLWRBAND  //优先级带数据可写
//下面三个revents不包含
POLLERR     //发生错误
POLLHUP     //发生挂起
POLLNVAL    //描述字不是一个打开的文件
  • out指定poll函数返回前等待多长时间,它是一个指定应等待毫秒数的正值。

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

  • nfds 是监控数组中有多少文件描述符需要被监控

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

select模型最多可以创建一个1024个文件描述符大小的集合,这是因为受到fd_set的固定数据类型的限制,而poll则没有这样的问题,因为分配一个pollfd结构的数组并把数组中的元素通知内核称为调用者的责任。但是poll模型任然使用的是轮询模型,效率比较低下。

2. poll模型实现

2.1 服务器端

#include "wrap.h"
#include <poll.h>
#include <limits.h>
#include <sys/stropts.h>#define MAXLINE         1024
#define INFTIM          -1
#define OPEN_MAX        3000
int main(int argc, char *argv[])
{int i, maxi, listenfd, connfd, sockfd;int nready;ssize_t n;char buf[MAXLINE];socklen_t clilen;struct pollfd client[OPEN_MAX];struct sockaddr_in clientaddr;listenfd = start_ser(argv[1], argv[2]);//监听文件描述符  该函数参考selectclient[0].fd = listenfd;//将监听文件描述符加入pollfd数组中client[0].events = POLLIN;//设置为输入可读for(i = 1; i < OPEN_MAX; i++){//初始化结构体数组client[i].fd = -1;}maxi = 0;while(1){nready = poll(client, maxi+1, INFTIM);  //阻塞等待注册时间发生if(client[0].revents & POLLIN){//当监听文件描述符响应有新连接请求clilen = sizeof(clientaddr);connfd = Accept(listenfd, (struct sockaddr *)&clientaddr, &clilen);//接受新客户for(i = 1; i < OPEN_MAX; i++){if(client[i].fd < 0){client[i].fd = connfd;  //把新客户的文件描述符加入数组break;}}if(i == OPEN_MAX){      //连接新客户上限Close(connfd);perr_exit("too many clients");}client[i].events = POLLIN;      //新客户端的处理事件if(i > maxi){maxi = i;       //更新最大值}if(--nready == 0){      //没有可读的描述符跳过本次循环continue;}}for(i = 1; i <= maxi; i++){     //请求所有客户端的数据if((sockfd = client[i].fd) < 0){continue;}if(client[i].revents & POLLIN){ //POLLIN事件发生memset(buf, '\0', MAXLINE);if((n = Read(sockfd, buf, MAXLINE-1)) < 0){if(errno == ECONNRESET){        //当客户端发送resetClose(sockfd);client[i].fd = -1;}else{perr_exit("read err");}}else if(n == 0){Close(sockfd);client[i].fd = -1;}else{printf("client : %s\n", buf);}if(--nready == 0){      //没有可读的描述符跳过本次循环break;}}}}Close(connfd);Close(listenfd);return 0;
}

2.2客户端

#include "wrap.h"int main(int argc, char *argv[])
{struct sockaddr_in serveraddr;int connfd;connfd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&serveraddr, sizeof(serveraddr));serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(atoi(argv[2]));inet_pton(AF_INET, argv[1], &serveraddr.sin_addr);Connect(connfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));char buf[1024];while((fgets(buf, 1024, stdin)) != NULL){Write(connfd, buf, strlen(buf));}Close(connfd);return 0;
}

2.3程序测试结果

Linux网络编程---I/O复用模型之poll相关推荐

  1. Linux网络编程---I/O复用模型之epoll

    https://blog.csdn.net/men_wen/article/details/53456474 Linux网络编程-I/O复用模型之epoll 1. epoll模型简介 epoll是Li ...

  2. Linux网络编程---I/O复用模型之select

    https://blog.csdn.net/men_wen/article/details/53456435 Linux网络编程-I/O复用模型之select 1. IO复用模型 IO复用能够预先告知 ...

  3. linux网络编程(三)select、poll和epoll

    linux网络编程(三)select.poll和epoll 一.为什么会有多路I/O转接服务器? 二.select 三.poll 三.epoll 一.为什么会有多路I/O转接服务器? 为什么会有多路I ...

  4. [Linux网络编程]高并发-Select模型

    概要介绍 一般情况下,处理socket通信一个线程或者进程在处理读写的时候要么阻塞在那一直等要么非阻塞然后过会查看是否可读可写,这样会浪费大量的资源,假如需要对多个套接字进行处理读写那么得开很多个线程 ...

  5. 第4章 Linux网络编程 24.端口复用

    目录 端口复用 查看网络相关信息的命令 端口复用 端口复用最常用的用途是: 防止服务器重启时之前绑定的端口还未释放 (2msl) 程序突然退出而系统没有释放端口 查看网络相关信息的命令 netstat ...

  6. Linux网络编程 之 IO复用epoll(十)

    1. epoll概述 相对于 select() 和 poll() 来说,epoll 更加灵活,没有描述符限制.epoll 使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个 ...

  7. Linux网络编程——I/O复用之select详解

    https://blog.csdn.net/lianghe_work/article/details/46506143 一.I/O复用概述 I/O复用概念: 解决进程或线程阻塞到某个 I/O 系统调用 ...

  8. Linux网络编程——I/O复用之poll函数

    一.回顾前面的select select优点: 目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点 select缺点: 1.每次调用 select(),都需要把 fd 集合从用户态拷贝到内核 ...

  9. linux 网络7层模型,Linux网络编程——OSI七层模型、TCP/IP模型

    OSI七层模型 开放式系统互连(Open System Interconnect),模型分为7层,从下往上依次为: 物理层: 数据链路层: 网络层: 传输层: 会话层: 表示层: 应用层: 记不住怎么 ...

最新文章

  1. 我看过的Java方面的好文章
  2. Python 爬虫实例(4)—— 爬取网易新闻
  3. loss和accuracy的关系
  4. 网易创新企业大会倒计时,云信将发布新一代音视频技术架构
  5. 【laravel5.4】重定向带参数
  6. cordova 某个页面强制横屏_小白科普:从输入网址到最后浏览器呈现页面内容,中间发生了什么?...
  7. UI-Day02--昨日作业代码(二)
  8. TypeScript基础入门 - 接口 - 简介
  9. mysql模式匹配详解_老生常谈MYSQL模式匹配 REGEXP和like的用法
  10. mysql如何查看事务日记_修复MySQL中人人头疼的Bug,看这篇就够
  11. 计算机中用于表示储存,计算机中用来表示存储器容量的基本单位是
  12. 计算机网络第三章:数据链路层
  13. GrayRhino轻松解锁卡贴机的越狱插件,不需要任何卡贴
  14. 《概率论与数理统计》作业一,python画频率分布表
  15. PS四种扁平化设计风格-网摘
  16. tomcat安装不上
  17. sqlserver插入数据时如何忽略主键重复的数据
  18. NAT ALG DNS — DNS在外部,内网通过域名访问内部服务器
  19. 使用 python进行文本处理
  20. 在oracle中要谨慎使用when others then(二)

热门文章

  1. 【基础中的基础】引用类型和值类型,以及引用传递和值传递
  2. python基础:迭代器、生成器(yield)详细解读
  3. Excel 一键上传到数据库
  4. 原生js使用forEach()与jquery使用each遍历数组,return false 的区别
  5. 使用 SqlDataSource 插入、更新和删除数据49
  6. 设计模式读书笔记-----备忘录模式
  7. linux c 指针数组定义数组长度,C/C++指针数组和 迪士尼源码搭建下载 数组指针...
  8. web 上传文件到linux没权限,Javaweb上传文件到Linux 没有读写权限
  9. html实现拖拽排序,简单的jquery拖拽排序效果实现代码
  10. java的前生今世_HBaseGC的前生今世-身世篇