当前位置: 首页 > news >正文

io多路复用之poll的详细执行过程

1.结构体struct pollfd的定义

struct pollfd {
    int   fd;        /* 文件描述符 */
    short events;    /* 想要监视的事件(input/output/priority) */
    short revents;   /* 实际发生的事件(返回的事件) */
};

2.定义pollfd数组,并设置listenfd想要监听的事件

    struct pollfd fds[POLL_SIZE]={0};//定义一个POLL_SIZE大小的pollfd数组fds[sockfd].fd=sockfd;fds[sockfd].events=POLLIN;//设置想要监听的事件为POLLIN

3.调用函数poll()监听事件的发生,并返回实际发生的事件

int nready=poll(fds,maxfd+1,-1);
printf("nready:%d\n",nready);//实际发生的事件的数量

int poll(struct pollfd *fds, nfds_t nfds, int timeout);
fds:一个指向 struct pollfd 结构体数组的指针,每个结构体描述了一个要监视的文件描述符及其关联的事件和发生的事件

nfds:表示文件描述符数组 fds 的大小,即要监视的文件描述符的数量。

timeout:超时值,指定 poll() 函数的阻塞时间。它可以有以下几种取值:

  • 传递负数:表示无限阻塞,poll() 函数将一直等待,直到至少一个文件描述符的事件发生。
  • 传递0:表示非阻塞模式,poll() 函数会立即返回,不管文件描述符的状态如何。
  • 传递正整数:表示超时时间(以毫秒为单位),poll() 函数会等待指定的毫秒数后返回,如果在超时前没有任何事件发生,它将返回0

注意:poll的返回值并不是clientfd(客户端)连接注册想要监听的事件,而是在这些已注册监听事件中实际发生的事件的个数. 

4.判断revent数值

在调用 poll 函数后,revents 字段会被设置为实际发生的事件。revents 字段是一个位掩码,它可以包含以下几个值中的一个或多个,表示文件描述符的状态:

  • POLLIN:文件描述符可以进行读取操作。
  • POLLOUT:文件描述符可以进行写入操作。
  • POLLERR:文件描述符发生了错误。
  • POLLHUP:文件描述符挂起(连接关闭)。
  • POLLNVAL:文件描述符无效。

 如果要检查文件描述符是否可以读取,可以执行以下操作:

if (revents & POLLIN) {// 文件描述符可以进行读取操作
}

只有当被监听的事件实际发生时才会执行 

demo: 


#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<fcntl.h>
#include<poll.h>#define PORT 8848#define POLL_SIZE 1024
#define BUFLEN 128int main(){int sockfd=socket(AF_INET,SOCK_STREAM,0);struct sockaddr_in serveraddr;memset(&serveraddr,0,sizeof(struct sockaddr_in));serveraddr.sin_family=AF_INET;serveraddr.sin_port=htons(PORT);serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);if(-1==bind(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr))){printf("bind failed\n");exit(1);}listen(sockfd,10);//poll/*struct pollfd {int   fd;        //文件描述符 short events;    // 想要监视的事件(input/output/priority) short revents;   // 实际发生的事件(返回的事件) };*/struct pollfd fds[POLL_SIZE]={0};fds[sockfd].fd=sockfd;fds[sockfd].events=POLLIN;int maxfd=sockfd;int clientfd=0;int count=0;while(1){printf("count:%d\n",count++);//打印while循环次数//sleep(10);//休眠10sint nready=poll(fds,maxfd+1,-1);printf("nready:%d\n",nready);//实际发生的事件的数量//reventif(fds[sockfd].revents&POLLIN){struct sockaddr_in clientaddr;socklen_t len=sizeof(clientaddr);clientfd=accept(sockfd,(struct sockaddr*)&clientaddr,&len);printf("new client:%d\n",clientfd);fds[clientfd].fd=clientfd;fds[clientfd].events=POLLIN;if(clientfd>maxfd){maxfd=clientfd;}if(nready-1==0){continue;}}int i=sockfd+1;for(;i<=maxfd;i++){char buffer[BUFLEN]={0};int ret=0;if(fds[i].revents&POLLIN){//只有事件实际发生时,该if程序才会被执行ret=read(fds[i].fd,buffer,BUFLEN-1);if(ret==0){//客户端主动关闭printf("client %d close\n",fds[i].fd);close(fds[i].fd);//关闭socket//重置fds[i].fd=-1;fds[i].events=0;continue;}buffer[ret]='\0';printf("recv from client:%d  buffer:%s\n",fds[i].fd,buffer);ret=write(fds[i].fd,buffer,strlen(buffer));}}}exit(0);
}

http://www.lryc.cn/news/168283.html

相关文章:

  • 网络安全深入学习第四课——热门框架漏洞(RCE— Log4j2远程代码执行)
  • 大数据Flink(八十一):SQL 时区问题
  • Input子系统 - Kernel驱动程序 - Android
  • MySQL里的查看操作
  • Vim的基础操作
  • 十天学完基础数据结构-第一天(绪论)
  • 神经网络 03(参数初始化)
  • div设置圆角#前端
  • Windows开机密码破解
  • Mobirise for Mac:轻松创建手机网站的手机网站建设软件
  • [npm] npx 介绍与使用说明
  • QT : 仿照QQ 完成弹出登录窗口,并实例化组件
  • typescrip接口 interface详解,以及ts实现多态
  • Vivado IP中Generate Output Products的设置说明
  • 9.3.5网络原理(应用层HTTP/HTTPS)
  • vue基础知识十一:Vue组件之间的通信方式都有哪些?
  • 高阶数据结构(2)-----红黑树(未完成)
  • [mockjs]Mock使用过程中的坑
  • 华为云云耀云服务器L实例评测|部署前后端分离项目
  • 02目标检测-传统检测方法
  • RP-母版 流程图 发布和预览 团队项目
  • 【第200篇原创文章】解决低于1%概率出现的芯片VPSS模块跑飞的问题
  • 微信小程序——生命周期详解(代码解读)
  • 多分类中混淆矩阵的TP,TN,FN,FP计算
  • Linux系统:OpenSSH7.4p升级到9.0p(服务器漏洞)
  • 【面试刷题】——C++的特点简单说明
  • C2基础设施威胁情报对抗策略
  • 差异备份详细说明(InsCode AI 创作助手)
  • flask要点与坑
  • EasyUI combobox 实现搜索(模糊匹配)功能