linux服务器开发(I/O多路复用技术)epoll的使用

本文介绍了Linux服务器开发中epoll的使用,详细讲解了EPOLLHUP与EPOLLRDHUP的区别,以及如何创建内核事件表、绑定套接字和事件,并提供了服务器端和客户端的DEMO示例。重点讨论了epoll的事件类型、操作和阻塞等待的机制。
摘要由CSDN通过智能技术生成

关键结构体

typedef union epoll_data {
   
    void        *ptr;
    int          fd;
    uint32_t     u32;
    uint64_t     u64;
} epoll_data_t;
struct epoll_event {
   
    uint32_t     events;      /* Epoll events */
    epoll_data_t data;        /* User data variable */ 
};

其中data用来存放套接字;

其中
events能够是下面几个宏的集合:
EPOLLIN :表示相应的文件描写叙述符能够读(包含对端SOCKET正常关闭);
EPOLLOUT:表示相应的文件描写叙述符能够写。
EPOLLPRI:表示相应的文件描写叙述符有紧急的数据可读(这里应该表示有带外数据到来);
EPOLLERR:表示相应的文件描写叙述符错误发生;
EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式。这是相对于水平触发(Level Triggered)来说的。
EPOLLONESHOT:仅仅监听一次事件。当监听完这次事件之后,就会把这个fd从epoll的队列中删除。

EPOLLHUP:表示相应的文件描写叙述符被挂断,

EPOLLRDHUP是:从Linux内核2.6.17开始由GNU引入的事件。当socket接收到对方关闭连接时的请求之后触发,有可能是TCP连接被对方关闭,也有可能是对方关闭了写操作。如果不使用EPOLLRDHUP事件,我们也可以单纯的使用EPOLLIN事件然后根据recv函数的返回值来判断socket上收到的是有效数据还是对方关闭连接的请求。

EPOLLHUP与EPOLLRDHUP的区别

PEOLLRDHUP

EPOLLRDHUP 表示读关闭。不是所有的内核版本都支持,没有查证。有两种场景:
1、对端发送 FIN (对端调用close 或者 shutdown(SHUT_WR)).

2、本端调用 shutdown(SHUT_RD). 当然,关闭 SHUT_RD 的场景很少。

EPOLLRDHUP 可以作为一种读关闭的标志,注意不能读的意思内核不能再往内核缓冲区中增加新的内容。已经在内核缓冲区中的内容,用户态依然能够读取到。

EPOLLHUP 表示读写都关闭:
1、本端调用shutdown(SHUT_RDWR)。

2、本端调用 shutdown(SHUT_WR),对端调用 shutdown(SHUT_WR)。

3、对端发送 RST.

发送 RST 的常见场景。

  1. 系统崩溃重启(进程崩溃,只要内核是正常工作都还能兜底,发送的是FIN,不是这里讨论的RST),四元组消失。此时收到任何数据,都会响应 RST.

2)设置 linger 参数,l_onoff 为 1 开启,但是 l_linger = 0 超时参数为0. 此时close() 将直接发送 RST.

  1. 接收缓冲区中还有数据,直接 close(), 接收缓冲区中的内容丢弃,直接发送 RST.

4)调用 close 时,close 会立马发送一个 FIN。注意:仅仅从 FIN 数据包上,无法断定对端是 close 还是仅仅 shutdown(SHUT_WR) 半关闭。往对端发送数据,若对端已经 close(),对端会回复 RST.

创建内核事件表

int epoll_create(int size);

参数:可以监控套接字的最大个数,但是在 Linux 2.6.8 内核版本以后,这个参数内核已经不再处理了(就是没有限制了),但是必须要大于1;

返回值:成功返回epoll文件描述符;失败返回-1

将需要监听的事件和对应的套接字绑定起来,并通过内核事件表的文件描述符对其操作

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

参数1:epoll描述符

第2个参数:对套接字绑定的事件进行相关操作:
op表示动作:用三个宏表示:
EPOLL_CTL_ADD:注冊新的fd到epfd中;
EPOLL_CTL_MOD:改动已经注冊的fd的监听事件;当某个fd已经注册了事件,只能修改不能新增,新增则报错;
EPOLL_CTL_DEL:从epfd中删除一个fd;

第3个参数:套接字文件描述符

第4个参数:内核事件表

返回值:成功返回0,失败返回非0

阻塞等待监听的事件发生

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

第一个参数:epoll描述符

第二个参数:第二个参数内核事件表

第三个参数;内核时间表中事件最大数

返回值:成功返回要处理的事件数,失败返回-1,超时返回0

作用:阻塞等待事件发生,返回须要处理的事件的数量,并将需处理事件的套接字集合于參数events内。參数timeout是超时时间(毫秒,0会马上返回(noblocking)。-1是永久堵塞)。该函数返回须要处理的事件数目。如返回0表示已超时。

使用epoll的DEMO如下

服务器端

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#</
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值