I/O多路复用

发布时间:2021-10-25 13:52:46

函数结构



int poll(struct pollfd* fds,nfds_t nfds,int timeout);


参数:


fds :?这是一个poll函数监听的结构列表,每一个元素中,包含以下的内容 (文件描述符、监听的事件集合、返回的事件集合)



nfds :?表示fds数组的长度

timeout :?这里是整型,单位就是毫秒,?timeout为0,-1,或者其他整数和select的含义是一模一样的;


?


返回值: 和select一模一样


0 :?函数等待超时

-1 :?出错

一个正整数 :?监听文件描述符就绪返回


?


events和revents


events:?关注事件(读就绪/写就绪/异常),输入的时候起作用


revents:?输出结果,输出的时候起作用


输入输出参数分离,并且每次调用的时候不需要重新设置


取值:(部分)


事件

描述

是否可作为输入

是否可作为输出

POLLIN

数据(包括普通数据和优先数据)可读

POLLOUT

数据(包括普通数据和优先数据)可写

POLLRDNORM

普通数据可读

POLLRDBAND

优先级带数据可读(Linux不支持)

POLLPRI

高优先级数据可读,比如TCP带外数据


?


poll优点



select使用了三个位图来表示三个fdset的方式,poll使用一个pollf指针实现

poll里包含了要监视的event和发生的event,使读写分离,每次循环不需要重新设置,接口使用方便

poll的文件描述符数量不受限制,一个数组可以开多大,就可以有多少个文件描述符,换句话说,只要内存足够,想开多少就开多少,但是太多了性能也会下降


?


poll缺点



当文件描述符很多的时候,依旧需要使用轮询的方式来获取文件描述符,效率低

每次调用poll也需要吧大量的pollfd结构从用户态拷贝至内核中,文件描述符很多事,效率也会很低

同时连接的大量客户在一时刻可能只有很少的处于就绪状态,因此随着监视的描述符数量的增长,其效率也会现行下降


?


代码1.用poll监视标准输入



#include
#include
#include

int main()
{
struct pollfd fds;
fds.fd = 0;
fds.events = POLLIN;
while(1)
{
int ret = poll(&fds,1,123456);
if(ret < 0)
{
perror("poll");
continue;
}
if(ret == 0)
{
printf("timeout...
");
continue;
}
if(fds.revents == POLLIN)
{
char buf[1024] = {0};
read(0,buf,sizeof(buf)-1);
printf("stdin: %s
",buf);
}
}
return 0;
}

结果演示:



代码2.多路转接服务器



// poll_server.c
#include
#include
#include
#include
#include
#include
#include
#include

typedef struct pollfd pollfd;

int ServerStart(short port)
{
int fd = socket(AF_INET,SOCK_STREAM,0);
if(fd < 0)
{
perror("socket");
return -1;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
if(bind(fd,(struct sockaddr*)&addr,sizeof(addr)) < 0)
{
perror("bind");
return -2;
}
if(listen(fd,5) < 0)
{
perror("listen");
return -3;
}
return fd;
}

void Init(pollfd* fd_list,int size)
{
int i = 0;
for(; i < size; ++i)
{
fd_list[i].fd = -1;
fd_list[i].events = 0;
fd_list[i].revents = 0;
}
}

void Add(int fd,pollfd* fd_list,int size)
{
int i = 0;
for(; i < size; ++i)
{
// 找到第一个空位将fd加入进去
if(fd_list[i].fd == -1)
{
fd_list[i].fd = fd;
fd_list[i].events = POLLIN;
break;
}
}
}

int main(int argc, char* argv[])
{
if(argc != 2)
{
printf("Usage: %s [port]
",argv[0]);
return 1;
}
int listen_sock = ServerStart(atoi(argv[1]));
if(listen_sock < 0)
{
printf("ServerStart Faild
");
return 1;
}
pollfd fd_list[1024];
Init(fd_list,sizeof(fd_list)/sizeof(pollfd));
Add(listen_sock,fd_list,sizeof(fd_list)/sizeof(pollfd));
// 进入事件循环
while(1)
{
int ret = poll(fd_list,sizeof(fd_list)/sizeof(pollfd),123456);
if(ret < 0)
{
perror("poll");
continue;
}
else if(ret == 0)
{
printf("time out...
");
continue;
}
size_t i = 0;
for(; i < sizeof(fd_list)/sizeof(pollfd); ++i)
{
if(fd_list[i].fd == -1)
{
continue;
}
if(!(fd_list[i].revents & POLLIN)) //如果输出参数不是pollin,就跳过
{
continue;
}
if(fd_list[i].fd == listen_sock)
{// 处理listen_sock情况
// 证明客户端已经连接上了,可以进行accept了
struct sockaddr_in client;
socklen_t len = sizeof(client);
int new_sock = accept(fd_list[i].fd,(struct sockaddr*)&client,&len);
if(new_sock < 0)
{
perror("accept");
continue;
}
Add(new_sock,fd_list,sizeof(fd_list)/sizeof(pollfd));
printf("[client: %d] connect
",new_sock);
}
else
{// new_sock已经就绪
// 可以进行读写了
char buf[1024] = {0};
ssize_t read_size = read(fd_list[i].fd,buf,sizeof(buf)-1);
if(read_size < 0)
{
perror("read");
continue;
}
if(read_size == 0)
{
printf("[client: %d] disconnect
",fd_list[i].fd);
fd_list[i].fd = -1;
fd_list[i].events = 0;
fd_list[i].revents = 0;
close(fd_list[i].fd);
}
printf("[client: %d] : %s
",fd_list[i].fd,buf);
write(fd_list[i].fd,buf,strlen(buf)); // 回显
} // end else
} // end for(; i < sizeof(fd_list)/sizeof(pollfd); ++i)
} // end while(1)
return 0;
}

?


客户端代码和select客户端代码一致,这里就不写了,需要的朋友可以移步?? ?I/O多路复用 - select


?

相关文档

  • 星星白天到哪里去了
  • 由阿里顶级专家联手写出:数据库高效优化架构、规范与SQL技巧
  • 电力设备有限公司简介
  • wadl文件能删除吗
  • 新硬盘要格式化吗
  • 节能宣传周活动主题绿色青山节能增效活动总结多篇
  • 别忘了给生活加点苦高三作文
  • 初三上册语文第三单元达标检测试题
  • R语言??一秒Logistic回归分析
  • 结婚朋友群怎么写好
  • 孕妇怎么样能不长斑
  • 班主任班级工作总结报告
  • 新闻学专业毕业生自荐书
  • 暑期志愿者实践报告
  • mysql查看数据类型命令
  • 手机屏幕怎么调颜色
  • 有关形容思考的句子56句
  • SQLite C-API带参数的查询/更新/删除操作
  • dubbo运行时报错Failed to invoke the method findAll in the service
  • 中考政治承担社会责任知识点梳理
  • 中国最恐怖的鬼片 中国最恐怖的鬼片电影
  • 最新周末送给朋友的祝福语集锦
  • 快手小时榜怎么弄
  • 选购鱼虾有什么窍门
  • 师德师风心得体会新版多篇
  • BUAAOJ989 御坂御坂 约瑟夫环
  • 爱护花草类的广告词
  • ERROR in : Cannot determine the module for class ManageDataComponent in D:/softDoc/javaweb_serve/hjp
  • win 10系统docker for windows 与 vmware关于Hyper-v问题
  • 导游证基础知识考试练习题及答案2017
  • 猜你喜欢

    电脑版