【Linux网络编程】epoll反应堆

本文详细介绍了Linux epoll反应堆模型的工作原理,通过实例展示了如何使用epoll实现并发服务器,包括创建监听、添加事件、处理读写事件和回调函数。重点在于反应堆模型的应用,即在网络数据处理后根据网络状态调整读写事件监听,确保高效数据传输。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

------------->【Linux系统编程/网络编程】(学习目录汇总) <--------------

1.epoll 反应堆模型:

实际上就是使用epoll的ET模式 + 非阻塞、轮询 + void *ptr(设置回调函数)。

接下来我们回顾一下之前用epoll实现的并发服务器

先使用 socket()、bind()、listen()创建套接字并初始化 --> epoll_create() 创建监听红黑树 --> 返回 epfd --> epoll_ctl() 向树上添加1个监听fd --> while(1)循环–> epoll_wait() 监听 --> 对应监听fd有事件产生 --> 返回监听满足数组。 --> 判断返回数组元素 --> 若lfd满足 --> 则调用Accept() -->若 cfd 满足 -->则调用 read() —> 小写转大写 --> write回去。

接下来再看看用epoll反应堆实现的并发服务器工作流程,实际上不同的是,在监听cfd过程中,不仅仅要监听 cfd 的读事件、还要监听cfd的写事件,并且分别对它们读写事件设置各自的回调函数。当各自对应的事件满足时,直接调用满足该事件的回调函数。

先使用socket()、bind()、listen()创建套接字并初始化 --> epoll_create() 创建监听红黑树 --> 返回 epfd --> epoll_ctl() 向树上添加一个监听fd --> while(1)循环 --> epoll_wait() 监听 --> 对应监听fd有事件产生 --> 返回监听满足数组。 --> 判断返回数组元素 -->若 lfd满足 --> Accept() -->若 cfd 满足 --> read() —> 小写转大写 --> cfd从监听红黑树上摘下 --> 设置EPOLLOUT监听写事件,设置回调函数 --> 调用epoll_ctl() 设置EPOLL_CTL_ADD 重新放到红黑上监听写事件 --> 等待 epoll_wait 返回 --> 说明 cfd 可写 --> write回去–> cfd从监听红黑树上摘下 -->设置 EPOLLIN监听读事件,设置回调函数 --> epoll_ctl()设置EPOLL_CTL_ADD 重新放到红黑上监听读事件 --> epoll_wait() 监听

反应堆的理解:加入IO转接之后,有了事件,server才去处理,这里反应堆也是这样,由于网络环境复杂,服务器处理数据之后,可能并不能直接写回去,比如遇到网络繁忙或者对方缓冲区已经满了这种情况,就不能直接写回给客户端。反应堆就是在处理数据之后,监听写事件,能写回给客户端了,才去做写回操作。写回之后,再改为监听读事件。如此循环。

大家可以结合这个视频p284集进行理解

点我查看

2.epoll反应堆代码实现

接下来直接看到代码吧:

/*************************************************************************
#	> File Name:server.c
#	> Author: Jay
#	> Mail: billysturate@gmail.com
#	> Created Time: Sun 23 Oct 2022 05:36:01 PM CST
 ************************************************************************/
#include <stdio.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

#define MAX_EVENTS  1024                                    //监听上限数
#define BUFLEN 4096
#define SERV_PORT   8080

void recvdata(int fd, int events, void *arg);
void senddata(int fd, int events, void *arg);

/* 描述就绪文件描述符相关信息 */

struct myevent_s {
   
   
    int fd;                                                 //要监听的文件描述符
    int events;                                             //对应的监听事件
    void *arg;                                              //泛型参数
    void (*call_back)(int fd, int events, void *arg);       //回调函数
    int status;                                             //是否在监听:1->在红黑树上(监听), 0->不在(不监听)
    char buf[BUFLEN];
    int len;
    long last_active;                                       //记录每次加入红黑树 g_efd 的时间值
};

int g_efd;                                                  //全局变量, 保存epoll_create返回的文件描述符
struct myevent_s g_events[MAX_EVENTS+1];                    //自定义结构体类型数组. +1-->listen fd


/*将结构体 myevent_s 成员变量 初始化*/

void eventset(struct myevent_s *ev, int fd, void (*call_back)(int, int, void *), void *arg)
{
   
   
    ev->fd = fd;
    ev->call_back = call_back;
    ev->events = 0;
    ev->arg = arg;
    ev->status = 0;
    memset(ev->buf, 0, sizeof(ev->buf));
    ev
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BillySturate

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值