Linux IO多路复用之poll
前面介绍了select,今天来介绍poll,poll 是一种高级的轮询的方法,通常用于服务器端处理多个客户端的请求的时候。 其作用于 select 很相似,但是较比 select 方法而言,效率更高,并且处理的连接个数不受内核的限制。 若是使用 select 来轮询客户端的连接,可以接受的连接个数与内核中进程所限定的可使用的文件描述符号的个数相同。 但是使用 poll 方法并不会有这种限制。
poll函数原型:
#include <poll.h>
int poll(struct pollfd fd[], nfds_t nfds, int timeout);
struct pollfd的结构如下:
struct pollfd {
int fd; //文件描述符
short events; //要求查询的事件掩码
short revents; //返回的事件掩码
};
- 第一个参数fds是pollfd结构体指针,可以指向一个结构体数组
- 第二个参数 nfds 制定数组中元素个数。
- 第三个参数指定 poll 函数返回前等待多长时间。 INFTIM 表示永远等待, 0 代表立即返回, > 0 等待指定数目的秒数。
代码:
#include"utili.h"
int main()
{
int sockfd;
int ret;
int MaxNum = 5;
struct sockaddr_in seraddr,cliaddr;
bzero(&seraddr,sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
seraddr.sin_port = htons(8000);
sockfd = socket(AF_INET,SOCK_STREAM,0);
ret = bind(sockfd,(struct sockaddr*)&seraddr,sizeof(seraddr));
if(ret < 0)
{
printf("bind error\n");
return -1;
}
ret = listen(sockfd,5);
if(ret < 1)
{
printf("listen error\n");
return -1;
}
struct pollfd client[MaxNum];
int i = 0, maxi = 0;
for(;i<MaxNum; i++)
client[i].fd = -1;//初始化poll结构中的文件描述符fd
client[0].fd = sockfd;//需要监测的描述符
client[0].events = POLLIN;//普通或优先级带数据可读
while(1)
{
//对加入poll结构体数组所有元素进行监测
ret = poll(client,maxi+1,-1);
if((client[0].events & POLLIN) == POLLIN)
{
int clilen = sizeof(cliaddr);
int connfd = 0;
// 从tcp完成连接中提取客户端
connfd = accept(sockfd,(struct sockaddr*)&cliaddr,&clilen);
// 将提取到的connfd放入poll结构体数组中,以便于poll函数监测
for(i=1;i<MaxNum;i++)
{
if(client[i].fd < 0)
{
client[i].fd = connfd;
client[i].events = POLLIN;
break;
}
}
if(i > maxi)
{
maxi = i;
}
if(--ret <= 0)
{
continue;
}
}
for(i=1;i<maxi;i++)
{
if(client[i].fd < 0)
continue;
if(client[i].events & (POLLIN | POLLERR))
{
int len=0;
char buf[128] = "";
//接受客户端数据
if((len = recv(client[i].fd, buf, sizeof(buf), 0)) < 0)
{
printf("recv error\n");
}
else if(len == 0)//客户端关闭连接
{
close(client[i].fd);
client[i].fd = -1;
}
else
send(client[i].fd, buf, len, 0);
//有的就绪描述符处理完了,就退出当前的for循环,继续poll监测
if(--ret <= 0)
break;
}
}
}
return 0;
}
这段代码有些问题,listen返回失败,思想是对的,有人可以改正的话,非常感谢!!!