高并发网络服务器-多路IO - epoll

发布时间:2023年12月18日

多路IO - epoll

将检测文件描述符的变化委托给内核去处理,然后内核将发生变化的文件描述符对应的事件返回给应用程序。

更多技术文档参见:https://github.com/IsConor/C_and_C_plus.git

函数介绍

Int epoll_create( int size );

函数说明:创建一个树根

参数说明

Size:最大节点数,此参数在Linux2.6.8已被忽略,但必须传递一个大于0的数

返回值

成功:返回一个大于0的文件描述符,代表整个树的树根。

失败:返回-1,并设置errno值。

函数介绍

Int epoll_ctl( int epfd, ?int op, ?int fd, ?struct epoll_event * event );

函数说明:将要监听的节点在epoll树上添加,删除和修改

参数说明

epfd: epoll树根

op:

EPOLL_CTL_ADD: 添加事件节点到树上

EPOLL_CTL_DEL: 从树上删除事件节点

EPOLL_CTL_MOD: 修改树上对应的事件节点

fd:事件节点对应的文件描述符

event:要操作的事件节点

typedef union epoll_data{

void ?????*ptr;

int ???????fd;

uint32_t ??u32;

uint64_t ??u64;

} epoll_data_t;

struct epoll_event {

uint32_t ??events;

epoll_data_t data;

};

event.events常用的有:

EPOLLIN: 读事件

EPOLLOUT:写事件

EPOLLERR:错误事件

EPOLLET:边缘触发模式

Event.data.fd: 要监控的事件对应的文件描述符

函数介绍

Int epoll_wait( int epfd, ?struct epoll_event * events, ?int maxevents, ?int timeout );

函数说明:委托内核监控epoll树的事件节点

函数参数

Epfd: epoll树根

Events: 传出参数,结构体数组

Maxevents:events数组大小

Timeout:

-1:一直阻塞

0:表示不阻塞

>0:表示超时的时长

使用epoll模型开发服务器流程:

1 设置socket,得到文件描述符lfd

2 设置端口复用 --- setsockopt()

3 绑定 --- bind()

4 监听 ---- listen()

5 创建一颗epoll树

Int epfd = epoll_create();

//将监听描述符上树

struct epoll_event ev;

ev.events = EPOLLIN;

ev.data.fd = lfd;

epoll_ctl( epfd, ?EPOLL_CTL_ADD, ?lfd, ?&ev );

Struct epoll_event events[1024];

While(1)

{

Nready = epoll_wait( epfd, ?events, ?1024, ?-1 );

If( nready < 0 )

{

If( errno == EINTR )

{

Continue;

}

Break;

}

For( i=0; i<nready; i++ )

{

Sockfd = events[i].data.fd;

//有客户端连接请求到来

If( sockfd == lfd )

{

cfd = accept( lfd, NULL, NULL );

//将cfd对应的读事件上epoll树

ev.data.fd = cfd;

ev.events = EPOLLIN;

epoll_ctl( epfd, ?EPOLL_CTL_ADD, ?cfd, ?&ev );

continue;

}

//有客户端发送数据过来

N = read( sockfd, ?buf, ?sizeof(buf) );

If(n <= 0)

{

Close(sockfd);

//将sockfd对应的事件节点从epoll树上删除

Epoll_ctl( epfd, ?EPOLL_CTL_DEL, ?sockfd, ?NULL );

Printf(“read error or client close\n”);

Continue;

}

Else

{

Write( sockfd, ?buf, ?n );

}

}

}

Close ( lfd );

Return 0;

进阶epoll

epoll的两种工作模式

epoll有两种工作模式 ET 和 LT 模式

水平触发:高电平代表1

只要缓冲区中有数据,就一直通知

边缘触发:电平有变化就代表1

缓冲区中有数据只会通知一次,之后再有数据才会通知

1 Epoll默认情况下是LT模式,在这种模式下,若读数据一次性没有读完,缓冲区内还有可读数据,则epoll_wait还会再次通知

2 若将epoll设置为ET模式,若读数据的时候一次性没有读完,则epoll_wait不再通知,直到下次有新的数据发来

Epoll的ET模式的非阻塞模式:

在ET模式下,如何在epoll_wait返回一次的情况下读完数据?

循环读数据,直到读完数据,但是读完数据后会阻塞

若能一次性读完,还需要设置什么?

将通信文件描述符设置为非阻塞

文章来源:https://blog.csdn.net/m0_73580128/article/details/132731469
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。