当前位置: 首页 > news >正文

从epoll事件的视角探讨TCP:三次握手、四次挥手、应用层与传输层之间的联系

目录

一、应用层与TCP之间的联系

二、 当通信双方中的一方如客户端主动断开连接时,仅是在客户端的视角下连接已经断开,在服务端的眼中,连接依然存在,为什么?——触发EPOLLRDHUP事件:对端关闭连接或停止写操作

 三、EPOLLIN:可读事件 和 EPOLLOUT:可写事件 的触发时机,什么时候设置读事件关心?什么时候设置写事件关心?

四、EPOLLPRI:优先处理数据事件 —— 当TCP报文携带的是紧急数据时触发(URG = 1, 紧急指针有效)


 

我们来回顾使用epoll的流程:

1、首先,创建监听套接字,将其设置为读事件关心并挂载到epoll的红黑树中。监听套接字读取事件就绪的条件是:TCP全连接队列不为空,在LT模式下,只要全连接队列中有数据就满足读时间就绪;在ET模式下,只有当全连接队列中有新连接到来时,才会触发一次读时间就绪。

2、当触发监听套接字读时间就绪后,使用epoll_wait从epoll模型的就绪队列中将就绪事件及其对应的套接字提取出来,根据套接字类型的不同和就绪事件的不同进而执行不同的回调函数。对于listen套接字而言,当读事件就绪后,它需要调用accept从TCP全连接队列中获取新连接的文件描述符。并将其挂载到epoll中,设置读事件关心。

3、当该连接接收到请求数据后,进行业务处理——根据请求构建响应数据放入该连接的用户级缓冲区中,并设置该连接的文件描述符为写事件关心,等待写事件的就绪。当epoll_wait获取到该连接的写事件就绪后再去执行写事件对应的回调函数。当写入完成后,需要关闭该连接的对写事件的关心。

4、当客户端主动关闭连接时,服务端需要先将连接接收缓冲区中的请求数据处理完毕,并且将数据处理的结果返回给客户端(这样做是出于逻辑的完善,具体情况看要看具体是怎样设计的)。当服务端发现客户端已经主动断开连接后,服务端也要断开连接,并清除文件描述符和移除epoll中对该文件描述符的关心,以及其他相关的资源。

在应用层中,当调用close函数关闭套接字文件描述符时视为发起断开连接。

一、应用层与TCP之间的联系

d7ec6d8ba28d40639225583d2a6c7073.png


接下来开始我们真正的问题讨论: 

二、 当通信双方中的一方如客户端主动断开连接时,仅是在客户端的视角下连接已经断开,在服务端的眼中,连接依然存在,为什么?——触发EPOLLRDHUP事件:对端关闭连接或停止写操作

套接字通信是全双工的,这意味着服务端和客户端之间可以同时进行通信,而要使得两者之间通信所传输的数据互不干扰,这就要求要为通信提供两个缓冲区,一个用来存储接收的数据,一个用于存储需要发送的数据。TCP为每个连接提供了两个独立的缓冲区:接收缓冲区和发送缓冲区。而客户端与服务端之间建立连接的实质就是通信双方是否能正常进行通信——即1、客户端是否能向服务端发送信息;2、服务端能否接收到客户端所发送的信息并且能否能否向客户端发送信息;3、客户端能否接收到服务端发送的信息。

4574c40f33e243eeac87f3af5b557398.png

以上过程实质上就是三次握手的验证过程,进行三次握手的目的就是验证通信双方是否具备通信的能力,即双方是否能够正常接收数据和发送数据。可见,客户端与服务端之间连接的建立实质上就是两者发送缓冲区与接收缓冲区之间的联系。

ab23c21afeb74e4d894e0b577503b4ea.png

当客户端主动调用close关闭连接时,实际上仅仅是客户端的发送缓冲区到服务端的接收缓冲区这条路线被切断了。对服务端而言,服务端的发送缓冲区到客户端的接收缓冲区之间的联系依旧存在。

8e1dc926724643f4925ca18fa474304c.png

所以,当客户端主动关闭连接时,我们需要及时调用read等函数将服务端接收缓冲区中的剩余数据读取至应用层并进行处理。数据处理完成后,如果有需要,可以继续发送给客户端。在数据清理完成后,服务端需要清理与该连接相关的资源。

250d802493454ce690fb244b21f3144c.png


 三、EPOLLIN:可读事件 和 EPOLLOUT:可写事件 的触发时机,什么时候设置读事件关心?什么时候设置写事件关心?

epoll所要做的就是等待资源就绪。

对于一条连接而言,在连接成功建立之初,我们就应对其设置读事件关心。——因为通信中的一方始终需要接收另一方发送的信息,继而要去对信息进行处理。这就需要我们调用read/recv等读取函数去读取接收缓冲区中的内容。但,缓冲区中如果没有数据,我们调用读取函数就会阻塞(BLOCK模式,连接关闭时返回0)或者读取失败(NONBLOCK模式,错误码为EAGAIN 或 EWOULDBLOCK,表示资源暂时不可用,连接关闭时返回0)。

那么读就绪的条件就是:在LT模式下,接收缓冲区中有数据即为读就绪。在ET模式下,接收缓冲区中接收到新数据即为读就绪。

类似的,写事件的就绪:在LT模式下,发送缓冲区中有空间即为写就绪。在ET模式下,发送缓冲区中有新空间即为写就绪。

但是,我们并不能在连接成功建立之初对其设置写事件关心!连接建立之初,发送缓冲区中一定是有空间的,因为此时我们并未将数据处理的结果写入到发送缓冲区中。如果此时设置了写事件关心,那么写事件是常就绪的,然而我们大多数的事件可能是在进行读取数据与业务处理,并不一定需要发送数据。同时,不必要的写事件常就绪还会造成epoll模型中红黑树和就绪队列资源的占用和不必要的资源浪费。

所以,我们要在需要写数据的时候将设置关心写事件——即当应用层处理完读取上来的请求数据并生成响应数据需要发送给另一方时,我们再将该连接描述符的写事件设置为关心。必要的,在数据发送完毕后,及时关闭对该连接的写事件关心。


四、EPOLLPRI:优先处理数据事件 —— 当TCP报文携带的是紧急数据时触发(URG = 1, 紧急指针有效)

8f27bc6477544904834e1026d48b532f.png

 当TCP报头中的保留位字段中的URG字段设置为1时,发送应用进程就告诉发送方的TCP有紧急数据要传送——该报文数据中包含紧急数据,于是发送方TCP就把紧急数据插入到本报文段数据的最前面,而在紧急数据后面的数据仍是普通数据。这时URG需要搭配首部中的紧急指针字段配合使用。

当接收方的接收缓冲区根据TCP报头识别到该段报文的数据包含紧急数据时,会通知与其相关的系统调用,epoll会返回EPOLLPRI事件。说明有紧急数据到来,需要优先处理。

 

 

 

相关文章:

从epoll事件的视角探讨TCP:三次握手、四次挥手、应用层与传输层之间的联系

目录 一、应用层与TCP之间的联系 二、 当通信双方中的一方如客户端主动断开连接时,仅是在客户端的视角下连接已经断开,在服务端的眼中,连接依然存在,为什么?——触发EPOLLRDHUP事件:对端关闭连接或停止写…...

Redis复制(replica)

Redis主从复制 [Redis主从复制](replica)是一个多Redis实例进行数据同步的过程,其中一个实例是主实例(Master),其他实例是从实例(Slave)。主实例负责处理命令请求,而从实…...

[云讷科技] 用于软件验证的仿真环境

我们使用Pursuit自动驾驶仪为各种场景设计仿真环境,以便用户可以在模拟环境中直接验证他们的软件,无需现场测试。该环境基于Gazebo引擎。 1. 工作区目录 模拟环境的工作区位于提供的U盘中的~/pursuit_space/sitl_space_pursuit中。用户可以按照用户手册…...

使用 Vite 和 Vue 框架创建组件库

在前端开发中,组件化开发已成为一种高效、可维护的方式。通过创建组件库,不仅可以提高代码复用率,还能方便地在不同项目之间共享组件。本文将详细介绍如何使用 Vite 和 Vue 框架创建一个组件库,并将其导出供其他项目使用。为保持一…...

【数据结构学习笔记】19:跳表(Skip List)

介绍 跳表是一个能在 O ( n l o g n ) O(nlogn) O(nlogn)时间完成查找、插入、删除的数据结构,相比于树形结构优点就是很好写(所以也用于实现Redis ZSet)。其核心思想就是维护一个元素有序的,能随机提升索引层数的链表。最下面一…...

【8】深入理解 Go 语言中的协程-从基础到高级应用

文章目录 一、引言 🌟二、协程基础概念 🧐(一)什么是协程(二)协程与线程、进程的区别三、协程的创建与启动 🚀(一)使用 go 关键字创建协程(二)简单…...

深入理解 ECMAScript 2024 新特性:字符串 isWellFormed 方法

ECMAScript 2024 引入了一个新的字符串实例方法:String.prototype.isWellFormed。这一新增功能是为了帮助开发者更容易地验证字符串是否为有效的 Unicode 文本。本文将详细介绍这一方法的使用场景、实现原理及其在实际应用中的价值。 String.prototype.isWellFormed…...

算法分析与设计之贪心算法

文章目录 前言一、Greedy Algorithms1.1 贪心选择性质1.2 最优子结构性质1.3 正确性证明 二、典型例题2.1 Interval Scheduling间隔调度2.2 Interval Partitioning最少间教室排课2.3 Selecting Breakpoints选择加油站停靠点2.4 硬币找零2.5 Scheduling to Minimizing Lateness2…...

Centos 宝塔安装

yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh 安装成功界面 宝塔说明文档 https://www.bt.cn/admin/servers#wcu 或者可以注册宝塔账号 1 快速部署 安装docker 之后 2 需要在usr/bin下下载do…...

蓝桥与力扣刷题(709 转换成小写字母)

题目:给你一个字符串 s ,将该字符串中的大写字母转换成相同的小写字母,返回新的字符串。 示例 1: 输入:s "Hello" 输出:"hello"示例 2: 输入:s "here…...

Redis的过期策略、内存淘汰机制

Redis只能存5G数据,可是你写了10G,那会删5G的数据。怎么删的?还有,你的数据已经设置了过期时间,但是时间到了,为什么内存占用率还是比较高? 一、Redis的过期策略 Redis采用的是定期删除惰性删除策略。 1…...

视觉多模态大模型---MiniMax-vl-01---以闪电般的注意力缩放基础模型

简介 MiniMax-VL-01 是与今年1月15日由上海稀宇科技有限公司(MiniMax)发布并开源的一款视觉多模态大模型,它与基础语言大模型 MiniMax-Text-01 一同构成了 MiniMax-01 系列。这款模型的设计初衷是为了应对日益增长的长上下文处理需求&#x…...

【微服务】面试 3、 服务监控 SkyWalking

微服务监控的原因 问题定位:在微服务架构中,客户端(如 PC 端、APP 端、小程序等)请求后台服务需经过网关再路由到各个微服务,服务间可能存在多链路调用。当某一微服务挂掉时,在复杂的调用链路中难以迅速确定…...

【案例81】NMC调用导致数据库的效率问题

问题现象 客户在使用NC系统时,发现系统特别卡顿。需要紧急排查。 问题分析 排查NMC发现,所有的线程都处于执行SQL层面,说明数据库当前出现了异常。查看数据库资源状态发现,Oracle相关进程CPU利用率达到了100%。 查看现在数据库…...

Linux_信号

信号的概念 && 知识补充 信号是进程之间事件异步通知的一种方式,是一种软中断。 标准信号:编号为1-31之间都是标准信号,这些都是预定义信号,用于通知进程发生的各种事件。实时信号:编号从32开始起均是实时信号…...

LeetCode100之搜索二维矩阵(46)--Java

1.问题描述 给你一个满足下述两条属性的 m x n 整数矩阵: 每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则,返回…...

学员答疑:安卓分屏窗口的TouchableRegion设置流程追踪

背景: vip学员在群里问到了一个分屏触摸区域设置的问题,开始以为就是和普通Activity设置区域没啥差别,都是在InputMonitor中进行的设置,但是仔细研究下来其实并不是哈。本文就带大家来手把手分析一下分屏情况下的触摸区域是怎么设置的。 d…...

[cg] UE5 调试技巧

UE 中 rhi命令的提交是在render 线程,而graphics api 真正的执行是在rhi 线程, 今天想看下rhi的底层调用,但由于是通过task执行的,无法获取到render thread传入的地方,调试起来不太方便。 可通过开启下面的命令来调试 …...

Python Wi-Fi密码测试工具

Python Wi-Fi测试工具 相关资源文件已经打包成EXE文件,可双击直接运行程序,且文章末尾已附上相关源码,以供大家学习交流,博主主页还有更多Python相关程序案例,秉着开源精神的想法,望大家喜欢,点…...

Linux 创建用户

Linux 创建用户 创建用户 sudo useradd -m -s /bin/bash test - -m:自动创建家目录 /home/test - -s /bin/bash:指定默认的 shell 为 bash修改密码 # 修改密码 sudo passwd test删除用户 userdel -r zengshun - -r:把用户的主目录一起删…...

自建RustDesk服务器

RustDesk服务端 下面的截图是我本地的一个服务器做为演示用,你自行的搭建服务需要该服务器有固定的ip地址 1、通过宝塔面板快速安装 2、点击【安装】后会有一个配置信息,默认即可 3、点击【确认】后会自动安装等待安装完成 4、安装完成后点击【打开…...

Spring Boot Web技术栈(官网文档解读)

摘要 Spring Boot框架既支持传统的Servlet技术栈,也支持新兴的响应式(Reactive)技术栈。本篇文章将详细讲述Spring Boot 对两种技术栈的详细支持和使用。 Servlet 概述 基于Java Servlet API构建,它依赖于传统的阻塞I/O模型&…...

【llama_factory】qwen2_vl训练与批量推理

训练llama factory配置文件 文件:examples/train_lora/qwen2vl_lora_sft.yaml ### model model_name_or_path: qwen2_vl/model_72b trust_remote_code: true### method stage: sft do_train: true finetuning_type: lora lora_target: all### dataset dataset: ca…...

wpa_cli命令使用记录

wpa_cli可以用于查询当前状态、更改配置、触发事件和请求交互式用户输入。具体来说,它可以显示当前的认证状态、选择的安全模式、dot11和dot1x MIB等,并可以配置一些变量,如EAPOL状态机参数。此外,wpa_cli还可以触发重新关联和IEE…...

【Uniapp-Vue3】页面生命周期onLoad和onReady

一、onLoad函数 onLoad在页面载入时触发,多用于页面跳转时进行参数传递。 我们在跳转的时候传递参数name和age: 接受参数: import {onLoad} from "dcloudio/uni-app"; onLoad((e)>{...}) 二、onReady函数 页面生命周期函数中的onReady其…...

《C++11》并发库:简介与应用

在C11之前,C并没有提供原生的并发支持。开发者通常需要依赖于操作系统的API(如Windows的CreateThread或POSIX的pthread_create)或者第三方库(如Boost.Thread)来创建和管理线程。这些方式存在以下几个问题: …...

LeetCode - #183 Swift 实现查询未下订单的客户

网罗开发 (小红书、快手、视频号同名) 大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等…...

HTML拖拽功能(纯html5+JS实现)

1、HTML拖拽--单元行拖动 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><…...

mysql 等保处理,设置wait_timeout引发的问题

&#x1f468;‍⚕ 主页&#xff1a; gis分享者 &#x1f468;‍⚕ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕ 收录于专栏&#xff1a;运维工程师 文章目录 前言问题处理 前言 系统部署完成后&#xff0c;客户需要做二级等保&…...

7.STM32F407ZGT6-RTC

参考&#xff1a; 1.正点原子 前言&#xff1a; RTC实时时钟是很基本的外设&#xff0c;用来记录绝对时间。做个总结&#xff0c;达到&#xff1a; 1.学习RTC的原理和概念。 2.通过STM32CubeMX快速配置RTC。 27.1 RTC 时钟简介 STM32F407 的实时时钟&#xff08;RTC&#xf…...