Linux-计算机网络-epoll的LT,ET模式

一.epoll的LT和ET模式介绍

epol 对文件描述符有两种操作模式:LT(Level Trigger,电平触发)模式和 ET(EdgeTrigger,边沿触发)模式。LT模式是默认的工作模式。当往epol 内核事件表中注册一个文件描述符上的 EPOLLET 事件时,epoll将以高效的 ET 模式来操作该文件描述符。

epoll的LT和ET模式区别示意图

二.epoll的ET模式如何处理

1.epoll的ET模式编程读取数据的处理方式
将描述符设置为非阻塞模式 +循环读取数据
也就是ET模式下的描述符必须是非阻塞的

2.将描述符设置为非阻塞模式的方法

//ser_epo11_ET.C
#include <fcntl.h>
void setnonblock(int fd)
{
int oldfl=fcntl(fd,F_GETFL);
int newfl=oldfl=O_NONBLOCK;

if(fcntl(fd,F SETFL,newfl)==-1)
perror("fcntl error\n");
}

三.ET模式的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include<fcntl.h>
#include<errno.h>
#define MAXFD 10

void setnoblock(int fd)
{
    int oldfl=fcntl(fd,F_GETFL);
    int newfl=oldfl|O_NONBLOCK;
    if(fcntl(fd,F_SETFL,newfl)==-1)
    {
        perror("fcntl error!\n");
    }


}
int create_socket()
 {
     int sockfd=socket(AF_INET,SOCK_STREAM,0);
     if(sockfd==-1)
     {
         return -1;
     }

     struct sockaddr_in saddr;
     memset(&saddr,0,sizeof(saddr));
     saddr.sin_family=AF_INET;
     saddr.sin_port=htons(6000);
     saddr.sin_addr.s_addr=inet_addr("127.0.0.1");

     int res=bind(sockfd,(struct sockaddr *)&saddr,sizeof(saddr));
     if(res==-1)
     {
         return -1;
     }

     res=listen(sockfd,5);
     if(res==-1)
     {
         return -1;
     }

     return sockfd;
 }
void epoll_add(int epfd,int fd)
{
    struct epoll_event ev;
    ev.events=EPOLLIN|EPOLLET;
    ev.data.fd=fd;

    setnoblock(fd);
  if(epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&ev)==-1)
  {
      perror("epoll ctl add err");
  }
}

void epoll_del(int epfd,int fd)
{
if(epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL)==-1)
    {
        perror("epoll ctl add err\n");
  }

}

int main()
{
    int sockfd=create_socket();
    assert(sockfd!=-1);

   int epfd=epoll_create(MAXFD);
   assert(epfd!=-1);

   epoll_add(epfd,sockfd);
   struct epoll_event evs[MAXFD];
   while(1)
   {
    int n=epoll_wait(epfd,evs,MAXFD,5000);
    if(n==-1)
    {
        perror("epoll_wait error\n");
continue;
    }
    else if(n==0)
    {
        printf("time out\n");
        continue;
    }
    else
    {

       for(int i=0;i<n;i++)
       {
           int fd=evs[i].data.fd;
         if(evs[i].events & EPOLLIN)
         {
           if(fd==sockfd)
           {
//accept
             struct sockaddr_in caddr;
             int len=sizeof(caddr);
             int c=accept(fd,(struct sockaddr *)&caddr,&len);
             if(c<0)
             {
             continue;
             }
             printf("accept c=%d\n",c);
             epoll_add(epfd,c);

           }
           else
           {
          // recv
             while(1)
             {
                 char buff[128]={0};
                 int num=recv(fd,buff,1,0);
                 if(num==-1)
                 {
                     if(errno!=EAGAIN && errno!=EWOULDBLOCK)
{
                         perror("recv err!");
                     }
                     else
                     {
                         send(fd,"ok",2,0);
                     }
                     break;
                 }
                 else if(num==0)
                 {
                     epoll_del(epfd,fd);
                     close(fd);
                     printf("client close\n");
                     break;
                 }
                 else
                 {
                     printf("buff(%d)=%s\n",fd,buff);
 }

             }


           }
         }

       }
    }
   }
   exit(0);




}


四.总结

ET模式下我们都需要做哪些事情?一共三点:
(1)添加事件类型的时候一定要添加上EPOLLET,这叫开启ET模式
(2)描述符要设置成非阻塞模式:
(3)在IO函数返回以后,就是epoll wait返回以后,它提醒我们描述符上有读事件产生了,我们要循环去处理;直到把这个描述符上的数据处理完;然后再去处理下一个描述符;
所以就是说ET模式下的编程就要求我们的描述符必须是非阻塞模式,

如下图:

对于 LT 模式操作的文件描述符,当 epoll wait 检测到其上有事件发生并将此事件通知应用程序
后,应用程序可以不立即处理该事件。这样,当应用程序下一次调用epoll wait 时,还会再次向
应用程序通告此事件,直到该事件被处理。
对于 ET 模式操作的文件描述符,当 epoll wait 检测到其上有事件发生并将此事件通知 应用程
序后,应用程序必须立即处理该事件,因为后续的 epoll wait 调用将不再向应用程序通知这一事
件。所以 ET模式在很大程度上降低了同一个 epol 事件被重复触发的次数,因此效率比 LT 模式
高。

五.EPOLLONESHOT事件

即使我们使用 ET模式,一个socket上的某个事件还是可能被触发多次。这在并发程序
中就会引起一个问题。比如一个线程(或进程,下同)在读取完某个socket上的数据后开
始处理这些数据,而在数据的处理过程中该socket上又有新数据可读(EPOLLIN再次被触
发),此时另外一个线程被唤醒来读取这些新的数据。于是就出现了两个线程同时操作一个
socket的局面。这当然不是我们期望的。我们期望的是一个socket连接在任一时刻都只被-
个线程处理。这一点可以使用epoll的EPOLLONESHOT事件实现。
对于注册了EPOLLONESHOT事件的文件描述符,操作系统最多触发其上注册的一个可
读、可写或者异常事件,且只触发一次,除非我们使用cpollct函数重置该文件描述符上注
册的 EPOLLONESHOT 事件。这样,当一个线程在处理某个socket时,其他线程是不可能有
机会操作该 socket的。但反过来思考,注册了EPOLLONESHOT事件的socket一旦被某个
线程处理完毕,该线程就应该立即重置这个socket上的EPOLLONESHOT事件,以确保这个
socket 下一次可读时,其EPOLLIN事件能被触发,进而让其他工作线程有机会继续处理这
个 socket。

原因:不希望出现两个线程同时操作一个socket的局面;
使用EPOLLONESHOT事件之后,当一个线程在处理某个socket时,其他线程时不可能有机会操作该
socket的.

六.同步非同步,阻塞非阻塞

Linux-计算机网络-探索epoll是同步阻塞的还是异步非阻塞的-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/904568.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

新160个crackme - 087-d4ph1-crackme2

运行分析 需破解Name和Serial PE分析 ASM程序&#xff0c;32位&#xff0c;无壳 静态分析&动态调试 ida找到关键字符串 INT_PTR __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4) {HICON IconA; // eaxint v5; // ediunsigned int v6; // ebxchar v7; // a…

leetcode 303.区域和检索-数组不可变

1.题目要求: 2.题目代码: class NumArray { public:vector<int> array;NumArray(vector<int>& nums) {array nums;}int sumRange(int left, int right) {int sum 0;while(left < right){sum array[left];left;}return sum;} };/*** Your NumArray obje…

【SVM手把手推导】对偶问题应用之支持向量机SVM(Hard Margin)

1. 对偶问题应用之支持向量机SVM 1.1 SVM 设给定数据集&#xff1a; { ( s i , y i ) : y i ∈ { 1 , − 1 } , i 1 , ⋯ , m } \{(\mathbf{s}^i,y^i):y^i\in\{1,-1\},i1,\cdots,m\} {(si,yi):yi∈{1,−1},i1,⋯,m}&#xff0c;我们想要找到一个决策超平面&#xff08;decis…

大数据技术的前景如何?

在当今数字化迅猛发展的时代&#xff0c;大数据技术的前景显得尤为广阔。随着数据量的激增&#xff0c;如何有效利用这些数据成为了各行各业关注的焦点。未来五年&#xff0c;大数据技术的发展趋势可以从市场规模、技术融合、行业应用和政策支持等多个方面进行深入分析。 1. 市…

【STM32】单片机ADC原理详解及应用编程

本篇文章主要详细讲述单片机的ADC原理和编程应用&#xff0c;希望我的分享对你有所帮助&#xff01; 目录 一、STM32ADC概述 1、ADC&#xff08;Analog-to-Digital Converter&#xff0c;模数转换器&#xff09; 2、STM32工作原理 二、STM32ADC编程实战 &#xff08;一&am…

推荐一款全新的视频编辑软件:CapCut剪映国际版

CapCut是一款全新的视频编辑应用程序&#xff0c;提供了各种功能和工具&#xff0c;让用户可以轻松地创建专业级别的视频。这款应用程序非常易于使用&#xff0c;功能强大&#xff0c;可供任何水平的用户使用。 CapCut包含了各种视频编辑工具&#xff0c;可以添加各种特效、滤镜…

提升用户体验优化全攻略

内容概要 用户体验&#xff08;UX&#xff09;在当今数字化时代扮演着举足轻重的角色。良好的用户体验不仅决定了用户对产品的满意度&#xff0c;还有助于提高转化率与客户忠诚度。因此&#xff0c;深入理解用户体验的重要性是每一个设计师和产品经理必须掌握的基础。在这一部…

关于springboot跨域与拦截器的问题

今天写代码的时候遇到的一个问题&#xff0c;在添加自己设置的token拦截器之后&#xff0c;报错&#xff1a; “ERROR Network Error AxiosError: Network Error at XMLHttpRequest.handleError (webpack-internal:///./node_modules/axios/lib/adapters/xhr.js:112:14) at Axi…

SDK和API

什么是SDK&#xff1f; SDK就像是一个超级工具箱&#xff0c;里面装满了各种工具、说明书和配件&#xff0c;帮你快速、方便地完成一项工作。比如&#xff0c;你要搭建一个乐高模型&#xff0c;SDK就是那个包含了所有乐高积木、拼装图纸、甚至一些特殊工具的大盒子。 什么是A…

【错误描述:“L2TP连接尝试失败,因为安全层在初始化与远程计算机的协商时遇到了一个处理错误”】

解决办法&#xff1a; 一、检查并更改网络协议 &#xff08;如果网络协议更改完成&#xff0c;还是链接失败&#xff0c;直接看 第二点&#xff09; 1、打开网络和Internet 设置 2、找到更改适配器选项 3、先择你要链接VPN&#xff0c;右键选择属性&#xff0c;之后选择安…

【网络】2.TCP通信

TCP通信 server1. 创建套接字2. 填充套接字3. 将套接字和监听文件描述符绑定4. 将_listensock设置为监听状态5. 启动服务器accept()函数read()函数 Server启动client1. 创建套接字2. 填充套接字connect()函数 3. 通过文件描述符向服务端发送信息 client启动 server server的启…

【ArcGISPro】宣布推出适用于 ArcGIS 的 AI 助手

此次分享了ESRI正在开发新的“AI 助手”来扩展ArcGIS应用程序&#xff0c;并且使用经过专门培训、提示工程和 LLM的“AI 助手”为这些应用程序提供特定技能。并且以视频的方式展示了如何使用生成式 AI 在ArcGIS应用程序中自动化和加速工作流。最后表示这些 “AI 助手”将在 202…

Ansible基本使用

目录 介绍 安装 inventory-主机清单 分组 子组 modules-模块 command shell script file copy systemd yum get_url yum_repository user mount cron 介绍 ansible是基于python开发的自动化运维工具。架构相对比较简单&#xff0c;仅需通过ssh连接客户机执行…

volatile如何保证可见性和禁止指令重排序?

当线程对volatile修饰的变量进行写操作时&#xff0c;JMM会插入一个写屏障&#xff0c;会强制的将本地内存中的数据写到主内存中 当线程对volatile修饰的变量进行读操作时&#xff0c;JMM会插入一个读屏障&#xff0c;会强制的让本地内存中数据失效&#xff0c;重新到主内存中读…

AUTOSAR_EXP_ARAComAPI的6章笔记(4)

☞返回总目录 相关总结&#xff1a;《AUTOSAR 自适应应用中原始数据流传输的使用方法》总结 6.4 原始数据流传输的使用方法 本章描述了原始数据流&#xff08;RawDataStreams&#xff09;在 AUTOSAR 自适应应用程序中的使用方法。 目前&#xff0c;原始数据流传输在单播 / …

input子系统的框架和重要数据结构详解

#1024程序员节 | 征文# 往期内容 I2C子系统专栏&#xff1a; 专栏地址&#xff1a;IIC子系统_憧憬一下的博客-CSDN博客具体芯片的IIC控制器驱动程序分析&#xff1a;i2c-imx.c-CSDN博客 – 末篇&#xff0c;有往期内容观看顺序 总线和设备树专栏&#xff1a; 专栏地址&#…

【Linux:网络基础】

网络协议&#xff1a; 协议实际上可以称为一种“约定”&#xff0c;通过网络通信中的数据约定&#xff0c;不同主机必须遵循相同的网络协议才可以实现通信。 协议即为通信双方都认识的结构化的数据类型 协议分层 协议的本质也是软件&#xff0c;在设计上为了更好的进行模块…

C++刷怪笼(9)继承

目录 1.前言 2.正文 2.1继承的概念和定义 2.1.1继承的概念 2.1.2继承的定义 ​编辑 2.1.3继承类模板 2.2基类和派生类间的转换 2.3继承中的作用域 2.3.1隐藏规则 2.4派⽣类的默认成员函数 2.4.1个常⻅默认成员函数 2.4.2实现⼀个不能被继承的类 2.5继承与友元 2.…

QT中使用图表之QChart概述

在Qt中使用QChart类可以快速绘制一个图表出来&#xff0c;比如折线图、饼图、柱状图等 QChart类用来管理图表中的图形、图例、轴等 QChartView是专门用来显示图表的类&#xff0c;相当于一个QWidget或者窗口&#xff0c;用来显示QChart 即总的步骤就是 1、创建QChartView的…

codeforces _ 补题

C. Ball in Berland 传送门&#xff1a;Problem - C - Codeforces 题意&#xff1a; 思路&#xff1a;容斥原理 考虑 第 i 对情侣组合 &#xff0c;男生为 a &#xff0c;女生为 b &#xff0c;那么考虑与之匹配的情侣 必须没有 a | b &#xff0c;一共有 k 对情侣&#x…