函数原型int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd *fds 表示一个结构体数组,是一个传入传出参数
nfds_t nfds 表示的是我们需要用到数组下标+1
以下为结构体
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};
传入时候管前两个fd events,传出的时候管最后一个revents
过程
poll里有三种事件,pollin(读事件) pollout(写事件) pollerr(异常事件)
需要让poll帮助我们监听lfd读事件
struct pollfd fds
fds[0].fd = lfd;
fds[0].events = POLLIN ;
int ret = poll(fds,nfds,-1)
![](https://img-blog.csdnimg.cn/e8ce91f3cd2041a3920ed0cddb794655.png)
![](https://img-blog.csdnimg.cn/ce6e53a986c5456c9b41156639b013db.png)
lfd(Fd = 3)后面的文件描述符系统帮我们管理,这里的nfds就传4,就是我们需要用到数组下标+1
返回的时候会更改Revents如果发生了Revents = POLLIN,如果未发生Revents = 0;
![](https://img-blog.csdnimg.cn/ab11e2da88ed46c9a188b3a4e215c50a.png)
返回之后判断
if(fds[0].revent & POLLIN)
{
int cfd = accept();
fds中选择一个合适的位置将cfd设置监听
}
之后在cfd里遍历
for(int i = 1;i<4;i++)
{
if(fds[i].revents & POLLIN)
{
cfd的事件触发
read(fds[i].fd,buf,sizeof(buf));
}
}
select和poll的区别
select受限只能1024个文件描述符,
poll可以监听更多文件描述符
poll比select浪费更多内存资源,有大量数据拷贝
多路io复用poll实现代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <poll.h>
#define BUFSIZE 1024
#define PORT 8000
int main()
{
int lfd, cfd;
char buf[BUFSIZE];
socklen_t addrlen;
lfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in ser_addr, cli_addr;
ser_addr.sin_family = AF_INET;
ser_addr.sin_port = htons(PORT);
ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(lfd, (struct sockaddr*)&ser_addr, sizeof(ser_addr));
listen(lfd,128);
socklen_t len = sizeof(cli_addr);
//已经有了一个文件描述符需要监听lfd
struct pollfd fds[1050];
int i = 0;
for(i = 0;i<1050;i++)
{
fds[i].fd = -1;
fd[i].events = 0;
}
int maxi;
fds[0].fd = lfd;
fds[0].evemt = POLLIN;
maxi = 0;
while(1)
{
int ret = poll()
}
return 0;
}