资讯 小学 初中 高中 语言 会计职称 学历提升 法考 计算机考试 医护考试 建工考试 教育百科
栏目分类:
子分类:
返回
空麓网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
空麓网 > 计算机考试 > 软件开发 > 后端开发 > Java

C语言笔记-27-网络-多路复用epoll

Java 更新时间: 发布时间: 计算机考试归档 最新发布

C语言笔记-27-网络-多路复用epoll

C语言笔记-27-网络-多路复用epoll


文章目录

  • C语言笔记-27-网络-多路复用epoll
  • 前言
  • 一、epoll 函数
    • 创建epoll实例(epoll例程)
    • 控制epoll
    • 等待检测epoll事件
  • 二、epoll 代码示例(结合TCP服务端)
  • 总结


前言

自学笔记,没有历史知识铺垫(省略百度部分)C语言笔记-27-网络-多路复用epoll


一、epoll 函数

注意 epoll在linux、unix中存在,macOS中没有,平替函数kqueue

创建epoll实例(epoll例程)

#include 
// 创建一个epoll实例,返回该实例的文件描述符.close()可以关闭文件描述符.
int epoll_create(int size);

参数

size 实例大小(必须大于0)

返回值

成功 文件描述符
错误 -1 errno被设置

控制epoll

#include 
// 控制epoll文件描述符
int epoll_ctl(int epfd,int  op, int fd, struct epoll_event *event);

参数

epfd 指定了要操作的epoll设备的文件描述符
op 改变fd相关事件

  1. EPOLL_CTL_ADD 新增fd相关的事件到epoll实例
  2. EPOLL_CTL_MOD 修改epoll实例中的fd相关的事件
  3. EPOLL_CTL_DEL 删除epoll实例中的fd

fd 指定了要代理的文件描述符
event 指定了跟fd相关的事件

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

返回值

成功 0
错误 -1 errno被设置

等待检测epoll事件

#include 
// 等待epoll实例代理检测的I/O事件
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

参数

epfd 指定epoll实例
events 将检测到的事件保存到events中
maxevents 设置最大检测事件数
timeout 设置等待的毫秒数(-1 一直等待到有事件)

返回值

成功 返回可用的文件描述符的最大个数(如果指定时间内没有I/O请求,0)
错误 -1 errno被设置

二、epoll 代码示例(结合TCP服务端)

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

// 校验错误工具
void check_err(int fd, char *title)
{
    if (fd == -1)
    {
        perror(title);
    }
}

// 启动服务函数
int start_server(short port)
{
    printf("服务器端启动中...n");

    // 使用sockaddr_in 替换 sockaddr
    struct sockaddr_in server_addr;
    // 家族簇
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    // 创建socket设备
    int sfd = socket(PF_INET, SOCK_STREAM, 0);
    check_err(sfd, "创建socket设备失败");

    // 绑定socket设备到ip、端口
    int bindResult = bind(sfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
    check_err(bindResult, "绑定socket设备失败");

    // 监听客户端消息到 链接未决队列
    int listenResult = listen(sfd, 10);
    check_err(listenResult, "监听socket设备失败");

    printf("服务器端启动成功,开始监听客户端消息...n");
    return sfd;
}
int main(int argc, char *argv[])
{

    // 启动服务
    int sfd = start_server(8089);

    // 1. 创建容量为2的epoll实例
    int efd = epoll_create(2);
    check_err(efd, "创建epoll实例失败");

    // 2. 将socket服务添加到epoll实例中,且指定模式为只读
    struct epoll_event e_event;
    // 只读
    e_event.events = EPOLLIN;
    // tcp服务端文件描述符
    e_event.data.fd = sfd;
    // 3. 控制epoll文件描述符 将sfd以e_event事件,加入到epoll实例中
    int ctl_result = epoll_ctl(efd, EPOLL_CTL_ADD, sfd, &e_event);
    check_err(ctl_result, "将socket服务添加到epoll实例失败");

    // 创建未决链接事件、IO事件容器
    struct epoll_event ew_event[100];
    while (1)
    {
        // 4. 等待检测epoll代理事件发生(此处存放未决链接事件和IO事件) 将接收的事件放入指定事件数量容器,且指定同时存储最大事件数
        int ewfd = epoll_wait(efd, ew_event, 90, -1);
        check_err(ewfd, "等待epoll链接失败");

        // 循环epoll事件容器 0时表示没有事件
        for (int i = 0; i < ewfd; i++)
        {
            // 链接事件描述符时,表示未决链接事件发生
            if (ew_event[i].data.fd == sfd)
            {
                // 从链接未决队列中取出未决链接
                int accept_result = accept(sfd, NULL, NULL);
                check_err(accept_result, "接收客户端消息失败");
                // 5. 将客户端链接的io读操作存入epoll实例
                e_event.events = EPOLLIN;
                e_event.data.fd = accept_result;
                int ctl_result2 = epoll_ctl(efd, EPOLL_CTL_ADD, accept_result, &e_event);
                check_err(ctl_result2, "将accept_result加到epoll实例失败");
            }
            else
            {
                // 客户端io读操作(在第5步加入到epoll进行管理的事件)
                char buf[128];
                // 读取客户端消息
                int r = read(ew_event[i].data.fd, buf, 128);
                // 处理客户端消息,返回给客户端
                write(ew_event[i].data.fd, buf, r);
                // 写入控制台展示
                write(1, buf, r);
                // 6. 移除客户端io读操作事件
                int ctl_result3 = epoll_ctl(efd, EPOLL_CTL_DEL, ew_event[i].data.fd, &e_event);
                check_err(ctl_result3, "将accept_result从epoll实例移除失败");
                // 结束客户端IO读写操作
                close(ew_event[i].data.fd);
            }
        }
    }

    return 0;
}

总结

本章主要为C语言笔记-27-网络-多路复用epoll

转载请注明:文章转载自 http://www.konglu.com/
本文地址:http://www.konglu.com/it/1094160.html
免责声明:

我们致力于保护作者版权,注重分享,被刊用文章【C语言笔记-27-网络-多路复用epoll】因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理,本文部分文字与图片资源来自于网络,转载此文是出于传递更多信息之目的,若有来源标注错误或侵犯了您的合法权益,请立即通知我们,情况属实,我们会第一时间予以删除,并同时向您表示歉意,谢谢!

我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2023 成都空麓科技有限公司

ICP备案号:蜀ICP备2023000828号-2