Linux 传输层协议 UDP 和 TCP
UDP 协议
UDP 协议端格式

- 16 位 UDP 长度, 表示整个数据报(UDP 首部+UDP 数据)的最大长度
- 如果校验和出错, 就会直接丢弃
UDP 的特点
- 无连接: 知道对端的 IP 和端口号就直接进行传输, 不需要建立连接
- 不可靠: 没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方,UDP 协议层也不会给应用层返回任何错误信息
- 面向数据报: 不能够灵活的控制读写数据的次数和数量,即应用层交给 UDP 多长的报文,UDP原样发送,既不会拆分,也不会合并
UDP 的缓冲区
UDP 使用注意事项
TCP 协议
TCP 协议段格式

- 源端口(16位):标识发送方的端口号,范围是0到65535。
- 目的端口(16位):标识接收方的端口号,范围是0到65535。
- 序列号(32位):用于标识每个报文段,使目的主机可确认已收到指定报文段中的数据。在SYN标志未置位时,该字段指示了用户数据区中第一个字节的序号;在SYN标志置位时,该字段指示的是初始发送的序列号。
- 确认号(32位):目的主机返回确认号,使源主机知道某个或几个报文段已被接收。如果ACK控制位被设置为1,则该字段有效。确认号等于顺序接收到的最后一个报文段的序号加1,这也是目的主机希望下次接收的报文段的序号值。
- 数据偏移(首部长度,4位):指出TCP报文段的数据起始处距离TCP报文段的起始处有多远,即首部长度。由于TCP报头的长度随TCP选项字段内容的不同而变化,因此报头中包含一个指定报头字段的字段。该字段以32比特为单位,所以报头长度一定是32比特的整数倍,有时需要在报头末尾补0。如果报头没有TCP选项字段,则报头长度值为5,表示报头一个有160比特,即20字节。
- 保留位(6位):由跟在数据偏移字段后的6位构成,全部为0。
- 控制位(6位):
- URG(紧急比特,1位):当URG=1时,表明紧急指针字段有效,它告诉系统此报文段中有紧急数据,应尽快传送。
- ACK(确认比特,1位):仅当ACK=1时确认号字段才有效,TCP规定,在连接建立后所有传达的报文段都必须把ACK置1。
- PSH(推送比特,1位):当两个应用进程进行交互式的通信时,有时在一端的应用进程希望在键入一个命令后立即就能够收到对方的响应。在这种情况下,TCP就可以使用推送(push)操作,这时,发送方TCP把PSH置1,并立即创建一个报文段发送出去,接收方收到PSH=1的报文段,就尽快地(即“推送”向前)交付给接收应用进程,而不再等到整个缓存都填满后再向上交付。
- RST(复位比特,1位):用于复位相应的TCP连接。
- SYN(同步比特,1位):仅在三次握手建立TCP连接时有效。当SYN=1而ACK=0时,表明这是一个连接请求报文段,对方若同意建立连接,则应在相应的报文段中使用SYN=1和ACK=1。因此,SYN置1就表示这是一个连接请求或连接接受报文。
- FIN(终止比特,1位):用来释放一个连接。当FIN=1时,表明此报文段的发送方的数据已经发送完毕,并要求释放运输连接。
- 窗口(16位):此字段用来进行流量控制,这个值是本机期望一次接收的字节数,即发送数据的窗口大小。告诉对方在不等待确认的情况下,可以发来多大的数据。这里表示的最大长度是2^16-1=65535,如需要使用更大的窗口大小,需要使用选项中的窗口扩大因子选项。指发送本报文段的一方的接收窗口(而不是自己的发送窗口)。
- 校验和(16位):源主机和目的主机根据TCP报文段以及伪报头的内容计算校验和。在伪报头中存放着来自IP报头以及TCP报文段长度信息。与UDP一样,伪报头并不在网络中传输,并且在校验和中包含伪报头的目的是为了防止目的主机错误地接收存在路由的错误数据报。
- 紧急指针(16位):仅在URG=1时才有意义,它指出本报文段中的紧急数据的字节数(紧急数据结束后就是普通数据),即指出了紧急数据的末尾在报文中的位置,注意:即使窗口为零时也可发送紧急数据。如果URG为1,则紧急指针标志着紧急数据的结束。其值是紧急数据最后1字节的序号,表示报文段序号的偏移量。
首部可变部分
- 选项字段:长度可变,最长可达40字节,当没有使用选项时,TCP首部长度是20字节。可能包括“窗口扩大因子”、“时间戳”等选项。
- 填充字段:用于保证任选项为32bit的整数倍。
数据部分
- 数据(长度可变):TCP首部结束之后的部分,其长度由IP包的长度减去IP头部长度和TCP头部长度得出。
确认应答(ACK)机制
- 数据发送:发送方将数据分割成较小的单元,称为TCP段,并为每个段分配一个唯一的序列号,实际上一个字节的数据对应一个序列号。然后将这些TCP段发送给接收方,并启动一个定时器来跟踪每个已发送段的确认。

- 数据接收与确认:接收方收到TCP段后,将按序将它们重新组装成完整的数据流。一旦接收方成功接收并处理了数据,它会发送一个确认(ACK)给发送方。确认中包含接收到的最高序列号,表示该序列号之前的所有数据都已正确接收。

- 发送方处理确认:发送方在接收到确认后,会停止相应定时器,并继续发送下一个序列号的TCP段。如果发送方在定时器超时之前未收到确认,它将重新发送未确认的TCP段。
超时重传机制

连接管理机制
- [CLOSED -> LISTEN] 服务器端调用 listen 后进入 LISTEN 状态, 等待客户端连接
- [LISTEN -> SYN_RCVD] 一旦监听到连接请求(同步报文段), 就将该连接放入内核等待队列中, 并向客户端发送 SYN 确认报文
- [SYN_RCVD -> ESTABLISHED] 服务端一旦收到客户端的确认报文, 就进入 ESTABLISHED 状态, 可以进行读写数据了
- [ESTABLISHED -> CLOSE_WAIT] 当客户端主动关闭连接(调用 close), 服务器会收到结束报文段, 服务器返回确认报文段并进入 CLOSE_WAIT
- [CLOSE_WAIT -> LAST_ACK] 进入 CLOSE_WAIT 后说明服务器准备关闭连接(需要处理完之前的数据); 当服务器真正调用 close 关闭连接时, 会向客户端发送 FIN, 此时服务器进入 LAST_ACK 状态, 等待最后一个 ACK 到来(这个 ACK 是客户端确认收到了 FIN)
- [LAST_ACK -> CLOSED] 服务器收到了对 FIN 的 ACK, 彻底关闭连接
- [CLOSED -> SYN_SENT] 客户端调用 connect, 发送同步报文段
- [SYN_SENT -> ESTABLISHED] connect 调用成功, 则进入 ESTABLISHED 状态, 开始读写数据
- [ESTABLISHED -> FIN_WAIT_1] 客户端主动调用 close 时, 向服务器发送结束报文段, 同时进入 FIN_WAIT_1
- [FIN_WAIT_1 -> FIN_WAIT_2] 客户端收到服务器对结束报文段的确认, 则进入 FIN_WAIT_2, 开始等待服务器的结束报文段
- [FIN_WAIT_2 -> TIME_WAIT] 客户端收到服务器发来的结束报文段, 进入TIME_WAIT, 并发出 LAST_ACK
- [TIME_WAIT -> CLOSED] 客户端要等待一个 2MSL(Max Segment Life, 报文最大生存时间)的时间, 才会进入 CLOSED 状态.
- 较粗的虚线表示服务端的状态变化情况
- 较粗的实线表示客户端的状态变化情况
- CLOSED 是一个假想的起始点, 不是真实状态
三次握手建立连接

- 第一次握手:客户端向服务器发送一个带有SYN(Synchronize Sequence Numbers,同步序列号)标志位的TCP数据包,请求建立连接。这个数据包中包含了客户端的初始序列号(ISN,Initial Sequence Number)。
- 第二次握手:服务器收到客户端的SYN请求后,会回复一个带有SYN和ACK(Acknowledgment,确认)标志位的数据包,称为SYN-ACK响应。这个响应中,服务器确认了客户端的SYN请求,并指定了服务器的初始序列号(ISN)。同时,服务器还会对客户端的初始序列号进行确认,即发送一个确认号(ACK号),表示已经收到客户端发送的序列号加1的数据。
- 第三次握手:客户端收到服务器的SYN-ACK响应后,会发送一个带有ACK标志位的数据包,表示确认了服务器的响应。这个ACK数据包中,客户端会确认收到了服务器的SYN响应,并指定了下一个要发送的序列号(即服务器的初始序列号加1)。至此,三次握手完成,TCP连接建立成功,双方可以开始进行数据传输。
四次挥手断开连接

- 第一次挥手:客户端发送一个FIN(Finish,结束)标志位的数据包,表示自己的数据已经发送完毕,请求关闭连接。此时客户端进入FIN_WAIT_1状态。
- 第二次挥手:服务器收到客户端的FIN包后,会发送一个ACK包进行确认,表示已经收到客户端的关闭请求。此时服务器进入CLOSE_WAIT状态,客户端进入FIN_WAIT_2状态。
- 第三次挥手:服务器在确认自己的数据也发送完毕后,会发送一个FIN包给客户端,表示自己也准备关闭连接。此时服务器进入LAST_ACK状态。
- 第四次挥手:客户端收到服务器的FIN包后,会发送一个ACK包进行确认。此时客户端进入TIME_WAIT状态,经过一段时间(通常为2MSL,Maximum Segment Lifetime,最大报文段生存时间)后,客户端进入CLOSED状态,服务器在收到客户端的ACK包后也进入CLOSED状态,连接彻底关闭。
理解 TIME_WAIT 状态
setsockopt()
要解决 TIME_WAIT 状态引起的 bind 失败的方法,我们可以使用 setsockopt 函数
int setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen); 参数说明:
- sock:将要被设置选项的套接字描述符。
- level:选项所在的协议层,常见的取值有SOL_SOCKET(通用套接字选项)、IPPROTO_IP(IP选项)、IPPROTO_TCP(TCP选项)等,使用 SOL_SOCKET 即可。
- optname:需要设置的选项名,如SO_BROADCAST、SO_REUSEADDR、TCP_NODELAY等,设置为 SO_REUSEADDR , 表示允许创建端口号相同但 IP 地址不同的多个 socket 描述符。
- optval:指向包含新选项值的缓冲区,根据选项名称的数据类型进行转换。
- optlen:现选项的长度。
返回值:
- 成功执行时,返回0。
- 失败返回-1,errno被设为以下的某个值:
- EBADF:sock不是有效的文件描述词。
- EFAULT:optval指向的内存并非有效的进程空间。
- EINVAL:在调用setsockopt()时,optlen无效。
- ENOPROTOOPT:指定的协议层不能识别选项。
- ENOTSOCK:sock描述的不是套接字。
使用如下:
int opt = 1;
setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); 滑动窗口
流量控制
拥塞控制
延迟应答
- 数量限制: 每隔 N 个包就应答一次
- 时间限制: 超过最大延迟时间就应答一次
TCP/UDP 对比
TCP与UDP的对比
| 对比维度 | TCP | UDP |
|---|---|---|
| 连接性 | 面向连接,需要建立连接(3次握手)和断开连接(4次挥手) | 无连接,不需要建立连接 |
| 可靠性 | 可靠交付,通过编号与确认、流量控制、计时器等机制保证数据无差错、不丢失、不重复且按序到达 | 不可靠交付,尽最大努力交付,但不保证可靠 |
| 报文首部 | 20字节,开销大 | 8字节,开销小 |
| 吞吐量控制 | 有拥塞控制、流量控制、重传机制、滑动窗口等机制 | 无 |
| 双工性 | 点对点全双工通信 | 支持一对一、一对多、多对一和多对多的交互通信 |
| 编程步骤 | 复杂,需要监听、接收、连接等步骤 | 简单,不需要监听和接收连接 |
| 使用场景 | 对传输效率要求低,但准确率要求高的场景,如HTTP、FTP、SMTP等 | 对传输效率要求高,但准确率要求低的场景,如DNS、NFS等 |
结论
- TCP:适用于需要可靠传输的场景,如文件传输、电子邮件等。
- UDP:适用于对实时性要求高,对可靠性要求不高的场景,如视频会议、直播等。
相关文章:
Linux 传输层协议 UDP 和 TCP
UDP 协议 UDP 协议端格式 16 位 UDP 长度, 表示整个数据报(UDP 首部UDP 数据)的最大长度如果校验和出错, 就会直接丢弃 UDP 的特点 UDP 传输的过程类似于寄信 . 无连接: 知道对端的 IP 和端口号就直接进行传输, 不需要建立连接不可靠: 没有确认机制, 没有重传机制; 如果因…...
Android开发EventBus
Android开发EventBus 分享一个EventBus 工具类,封装一下,让你少写些代码 直接上代码: public class BaseEventBusUtils {public static void register(Object subscriber) {EventBus eventBus EventBus.getDefault();if (!eventBus.isReg…...
chrome浏览器chromedriver下载
chromedriver 下载地址 https://googlechromelabs.github.io/chrome-for-testing/ 上面的链接有和当前发布的chrome浏览器版本相近的chromedriver 实际使用感受 chrome浏览器会自动更新,可以去下载最新的chromedriver使用,自动化中使用新的chromedr…...
第一个Qt开发实例(一个Push Button按钮和两个Label)【包括如何在QtCreator中创建新工程、代码详解、编译、环境变量配置、测试程序运行等】
目录 Qt开发环境QtCreator的安装、配置在QtCreator中创建新工程在Forms→mainwindow.ui中拖曳出我们要的图形按钮查看拖曳出按钮后的代码为pushButton这个图形添加回调函数编译工程关闭开发板上QT的GUI(选做)禁止LCD黑屏(选做)设置Qt运行的环境变量运行Qt程序如何让程序在系统启…...
【react+redux】 react使用redux相关内容
首先说一下,文章中所提及的内容都是我自己的个人理解,是我理逻辑的时候,自我说服的方式,如果有问题有补充欢迎在评论区指出。 一、场景描述 为什么在react里面要使用redux,我的理解是因为想要使组件之间的通信更便捷…...
【435. 无重叠区间 中等】
题目: 给定一个区间的集合 intervals ,其中 intervals[i] [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 。 注意 只在一点上接触的区间是 不重叠的。例如 [1, 2] 和 [2, 3] 是不重叠的。 示例 1: 输入: intervals …...
文献学习笔记:中风醒脑液(FYTF-919)临床试验解读:有效还是无效?
【中风醒脑液(FYTF-919)临床试验解读:有效还是无效?】 在发表于 The Lancet (2024 年 11 月 30 日,第 404 卷)的临床研究《Traditional Chinese medicine FYTF-919 (Zhongfeng Xingnao oral pr…...
4 前端前置技术(中):node.js环境
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 前言...
5.角色基础移动
能帮到你的话,就给个赞吧 😘 文章目录 角色的xyz轴与移动方向拌合输入轴值add movement inputget controller rotationget right vectorget forward vector 发现模型的旋转改变后,xyz轴也会改变,所以需要旋转值来计算xyz轴方向。 …...
vue2语法速通
首先,git clone下来的项目要npm install下载依赖,如果是vue项目,运行通常npm run serve或者npm run dev vue速通一下 使用vite创建项目(较快) npm create vite 配置文件 src/ ├── assets/ # 存放…...
doris:基于导入的批量删除
基于导入的批量删除 删除操作可以视为数据更新的一种特殊形式。在主键模型(Unique Key)表上,Doris 支持通过导入数据时添加删除标记来实现删除操作。 相比 DELETE 语句,使用删除标记在以下场景中具有更好的易用性和性能优势&a…...
【商品库存管理——差分、前缀和】
题目 代码 #include <bits/stdc.h> using namespace std; const int N 3e510; int l[N], r[N], b[N]; int s1[N], s0[N]; int main() {int n, m;cin >> n >> m;for(int i 1; i < m; i){cin >> l[i] >> r[i];b[l[i]], b[r[i]1]--;}int a 0…...
Linux基本指令2
07.man指令(重要): Linux的命令有很多参数,我们不可能全记住,我们可以通过查看联机手册获取帮助。访问Linux手册页的命令是 man 语法: man [选项] 命令 man ls查看ls指令更多的说明。 man man: man指令就…...
运维监控平台 WGCLOUD
WGCLOUD v3.5.7 于 2025 年 2 月 3 日发布1。这是一款开源免费的分布式运维监控平台,server 端基于 springboot 开发,agent 端使用 go 编写1。以下是 v3.5.7 版本的更新内容1: 2. 自定义告警批量添加设置 3. 告警通知渠道设置 4. 告警规则设置…...
GDAL矢量数据集相关接口的资源控制问题
1. 引言 笔者在《使用GDAL读写矢量文件》这篇文章中总结了通过GDAL读写矢量的具体实现。不过这篇文章中并没有谈到涉及到矢量数据集相关接口的资源控制问题。具体来说,GDAL/OGR诞生的年代连C语言本身都不是很完善(c11之前),因此提…...
Android学习19 -- 手搓App
1 前言 之前工作中,很多时候要搞一个简单的app去验证底层功能,Android studio又过于重型,之前用gradle,被版本匹配和下载外网包折腾的堪称噩梦。所以搞app都只有找应用的同事帮忙。一直想知道一些简单的app怎么能手搓一下&#x…...
人工智能导论-第3章-知识点与学习笔记
参考教材3.2节的内容,介绍什么是自然演绎推理;解释“肯定后件”与“否定前件”两类错误的演绎推理是什么意义,给出具体例子加以阐述。参考教材3.3节的内容,介绍什么是文字(literal);介绍什么是子…...
wxWidgets中wxGrid表格使用示例,去掉竖向表头
这里设置表格各种属性如下: // 去掉竖向表头 grid->SetRowLabelSize(0); // 设置表格背景色为黑色 grid->SetDefaultCellBackgroundColour(*wxBLACK); // 设置单元格内容居中,字体为16号,白色 wxFont cellFont(16, wxFONTFAMILY_DEFAULT, wx…...
全面掌握市场信息:xtquant库在证券品种数据获取中的应用
全面掌握市场信息:xtquant库在证券品种数据获取中的应用 开篇点题:技术背景和应用场景 在量化交易领域,快速准确地获取市场基础信息是至关重要的。xtquant库提供了一种便捷的途径来获取各类证券品种的数据,包括股票、指数、基金等…...
DeepSeek 的含金量还在上升
大家好啊,我是董董灿。 最近 DeepSeek 越来越火了。 网上有很多针对 DeepSeek 的推理测评,除此之外,也有很多人从技术的角度来探讨 DeepSeek 带给行业的影响。 比如今天就看到了一篇文章,探讨 DeepSeek 在使用 GPU 进行模型训练…...
day38|leetcode 322零钱兑换,279.完全平方数,139.单词拆分
322. 零钱兑换 给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。 计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。 你可以认为每种硬币的数量是…...
【Linux系统】信号:信号保存 / 信号处理、内核态 / 用户态、操作系统运行原理(中断)
理解Linux系统内进程信号的整个流程可分为: 信号产生 信号保存 信号处理 上篇文章重点讲解了 信号的产生,本文会讲解信号的保存和信号处理相关的概念和操作: 两种信号默认处理 1、信号处理之忽略 ::signal(2, SIG_IGN); // ignore: 忽略#…...
Go语言指针的解引用和间接引用
在 Go 语言中,"解引用"和"间接引用"是与指针相关的概念。 解引用 (Dereferencing): 解引用是指通过指针访问它所指向的变量的值。在 Go 中,使用星号(*)来解引用一个指针。 例如: v…...
【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.6 广播机制核心算法:维度扩展的数学建模
2.6 广播机制核心算法:维度扩展的数学建模 目录/提纲 #mermaid-svg-IfELXmhcsdH1tW69 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-IfELXmhcsdH1tW69 .error-icon{fill:#552222;}#mermaid-svg-IfELXm…...
硬件产品经理:需求引力模型(DGM)
目录 1、DGM 模型简介 2、理论核心:打破传统线性逻辑 3、三大定律 第一定律:暗物质需求法则 第二定律:引力井效应 第三定律:熵减增长律 4、落地工具包 工具1:需求密度热力图 工具3:摩擦力歼灭清单…...
基于“蘑菇书”的强化学习知识点(四):贝尔曼方程
贝尔曼方程 摘要贝尔曼方程(Bellman Equation)详解1. 核心思想2. 基本概念3. 贝尔曼方程的两种形式(1) 状态值函数的贝尔曼方程(2) 动作值函数的贝尔曼方程 4. 贝尔曼最优方程(Bellman Optimality Equation)5. 示例:网…...
Guided Decoding (借助FSM,有限状态自动机)
VLLM对结构化输出的支持: vllm/docs/source/features/structured_outputs.md at main vllm-project/vllm GitHub VLLM对tool call的支持: vllm/docs/source/features/tool_calling.md at main vllm-project/vllm GitHub 以上指定输出格式…...
ComfyUI工作流 图像反推生成人像手办人像参考(SDXL版)
文章目录 图像反推生成人像手办人像参考SD模型Node节点工作流程效果展示开发与应用图像反推生成人像手办人像参考 本工作流旨在通过利用 Stable Diffusion XL(SDXL)模型和相关辅助节点,实现高效的人像参考生成和手办设计。用户可通过加载定制的模型、LORA 调整和控制节点对…...
C++11新特性之long long超长整形
1.介绍 long long 超长整形是C11标准新添加的,用于表示更大范围整数的类型。 2.用法 占用空间:至少64位(8个字节)。 对于有符号long long 整形,后缀用“LL”或“II”标识。例如,“10LL”就表示有符号超长整…...
【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.5 高级索引应用:图像处理中的区域提取
2.5 高级索引应用:图像处理中的区域提取 目录/提纲 #mermaid-svg-BI09xc20YqcpUam7 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-BI09xc20YqcpUam7 .error-icon{fill:#552222;}#mermaid-svg-BI09xc20…...
