一般用于服务器监听某一个文件描述符;和select相似
1、创建红黑树,用于监听文件描述符
#include <sys/epoll.h>
int epoll_create(int size)
功能:创建红黑树
参数:size:写大于0即可
返回值:数的句柄
2、节点上树、节点下树、修改树节点
#include <sys/epoll.h>
int epoll_ctl(int efd,int op,int fd,struct epoll_event *event)
功能:
参数:epfd:树的根节点(句柄)
op:
EPOLL_CTL_ADD
EPOLL_CTL_MOD
EPOLL_CTL_DEL
fd:需要上树监听的文件描述符
event:一个树上的节点,
typedef union epoll_data{
void *ptr;
int fd;//需要监听的文件描述符
unit32_t u32;
unit64_t u64;
}epoll_data_t;
struct epoll_event{
unit32_t events;
epoll_data_t data;
}这是一个上下树节点的全部信息,包括事件和文件描述符;
于是用户态定义接收的数组也应该是这种类型的结构体
events:可以选择的事件有很多,包括写读什么的;
EPOLLIN写事件;
EPOLLOUT读事件;
返回值:成功返回0,失败返回1
3、监听
#include <sys/epoll.h>
int epoll_wait(int efd, srtuct epoll_event *ev,int maxevent,int timeout)
功能:
参数:
epfd 树的根节点
ev:用于接收树变化struct epoll_event数组元素首地址
maxevent:数组元素的个数
timeout:-1永久监听;>0限时间
返回值:变化文件描述符的个数
使用案例:
int main(int argc, char **argv)
{
//1、创建套接字
//2、绑定
int lfd = tcp4bind(7777,NULL);
//3、监听
listen(lfd, 128);
//创建树
int epfd=epoll_create(1);
//将lfd上树
struct epoll_event ev;
ev.events=EPOLLIN; //读事件
ev.data.fd=lfd;
epoll_ctl(epfd, EPOLL_CTL_ADD,lfd, &ev)
//循环监听树
while(1)
{
struct epoll_event evs[1024]; //用户态创建的用于监听文件描述符
int n = epoll_wait(epfd, evs, 1024, -1);
if(n<0) perror("");
else if(n>=0)
{
for(int i=0; i<n; i++)
{
int fd= evs[i].data.fd;
if(fd == lfd && evs[i].events&EPOLLIN) //返回的事件位与读事件
//如果位与是非0值就代表产生了读事件
{
struct sockaddr_in cliaaddr;
socklen_t len=sizeof(cliaddr);
char ip[16]=" ";
int cfd=Accept(lfd, (struct sockaddr*)&cliaddr, &len);
printf("client ip=%s, port=%d\n",
inet_ntop(AF_INET,&cliaddr.sin_addr.s_addr, ip, 16),
ntohs(cliaddr.sin_port));
//将cfd上树
ev.events=EPOLLIN; //读事件
ev.data.fd=cfd;
epoll_ctl(epfd, EPOLL_CTL_ADD,cfd, &ev)
}
else if(fd == lfd && evs[i].events&EPOLLOUT) 同理写事件
{
char buf[1500]=" ";
int count = read(fd, buf, sizeof(buf));
if(count <=0)
{
perror("");
//下树关闭文件描述符
...
}
else
{
write(fd,buf, sizeof(buf));
}
}
}
}
}
//处理
}