epoll 的LT与ET实例

本文介绍了epoll的数据结构、函数以及两种触发模式——LT和ET。在LT模式下,epoll允许分多次接收数据,而在ET模式下,epoll能一次性处理所有数据,提高效率。此外,文章提到了在ET模式下遇到的一个epoll_wait问题,返回值始终为0,且event中包含可读事件,作者对此感到困惑并希望得到解答。
摘要由CSDN通过智能技术生成

epoll的数据结构与函数

epoll需要使用struct epoll_event 来记录需要监听的事件,将需要监听的文件描述符记录在epoll_event.data.fd中,将需要监听的事件记录在epoll_event.events中,常见的监听事件包括:

  • EPOLLIN:读事件;
  • EPOLLOUT:写事件;
  • EPOLLRDHUP:读关闭事件,本端调用shutdown(SHUT_RD)或对端调用shutdown(SHUT_WR);
  • EPOLLHUP:读写关闭事件,本端调用shutdown(SHUT_RDWR)或本端调用shutdown(SHUT_WR)且对端调用shutdown(SHUT_WR);
  • EPOLLERR:文件描述符错误事件;

epoll监听通过三个函数来完成:

  • epoll_create(int size):创建epoll实例,也可以使用epoll_create1(int flags)函数,传入的参数实际无意义,只要大于0即可;
  • epoll_ctl(int epfd, int op, int fd, struct epoll_event *event):修改epoll实例,op对epoll的操作,常见的操作如下:
  1. EPOLL_CTL_ADD:将fd的监听事件event添加到epfd上;
  2. EPOLL_CTL_DEL:将fd的监听事件event从epfd上去除;
  3. EPOLL_CTL_MOD:修改fd在epfd上的监听事件为event。
    epoll_ctl设置的event选项常见的如下:
  4. EPOLLET:设置ET触发模式;
  5. EPOLLONESHOT:设置只监听一次事件,如果希望再监听事件需要再次使用EPOLL_CTL_ADD添加监听事件。
  • epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout):用于等待io事件,timeout设置为-1时,为阻塞模式。

epoll的LT触发模式

epoll默认触发模式是LT触发模式,LT模式下,epoll接收数据不需要一次全部接收,未接收的数据会在下次触发时继续读取。

#include <unistd.h>
#include <iostream>
#include <string>
#include <sys/socket.h>
#include <errno.h>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <signal.h>
#include <netdb.h>
#include <sys/types.h>

//设置地址可重用
static int setReuseAddr(int fd){
   
    if(fd < 0) return -1;
    int on = 1;
    if (setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
   
        return -1;
    }
    return 0;
}

int main(){
   
    
    const int port = 9007;
    const int MAX_EVENT = 20;

    struct epoll_event ev, event[MAX_EVENT];

    const char * const local_addr = "127.0.0.1";
    struct sockaddr_in server_addr = {
    0 };
    //初始化socket
    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (-1 == listenfd) {
   
        std::cout << "create listenfd failed:" << strerror(errno) << std::endl;
        return -1;
    }
    
    if (setReuseAddr(listenfd) < 0){
   
        std::cout << "set reuse addr failed:" << strerror(errno) << std::endl;
        close(listenfd);
        return -1;
    }

    server_addr.sin_family = AF_INET;
    inet_aton( local_addr, &(server_addr.sin_addr));
    server_addr.sin_port = htons(port);

    if (bind(listenfd, (const struct sockaddr *)&server_addr, sizeof (server_addr)) < 0) {
   
        std::cout << "bind port failed:" << strerror(errno) << std::endl;
        close(listenfd);
        return -1;
    }

    if (listen(listenfd, 200)</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值