2025-01-15🌱上海: ☀️ 🌡️+6°C 🌬️↓18km/h
# TCP 和 UDP 有什么区别?
TCP 提供了可靠、面向连接的传输,适用于需要数据完整性和顺序的场景
UDP 则提供了更轻量、面向报文的传输,适用于实时性要求高的场景。
(后序会具体分析讲解什么面向报文与面向连接)
区别总结:
特性 | TCP | UDP |
---|---|---|
连接方式 | 面向连接 | 无连接 |
可靠性 | 提供可靠性,保证数据按顺序到达 | 不可靠,不保证顺序或完整性 |
流量控制 / 拥塞控制 | 提供流量控制和拥塞控制 | 没有流量控制和拥塞控制 |
顺序保证 | 保证数据顺序 | 不保证数据顺序 |
头部大小 | 较大(20 字节及以上) | 较小(8 字节) |
性能 | 较低,延迟大 | 较高,延迟小 |
数据传输模式 | 字节流传输模式 | 数据报传输模式 |
适用场景 | 文件传输、Web、邮件等需要可靠性的应用 | 实时通讯、语音、视频、游戏等高性能要求应用 |
基于两者的协议 | 1. HTTP 协议:主要用于超文本和多媒体内容的协议。<br>2. HTTPS 协议:在 HTTP 协议上加了一层 SSL/TLS 的外壳,可靠性和安全性有了一定保证。<br>3. FTP 协议:文件传输协议,常见的像学生上传作业到学校的 FTP 上。<br>4. SMTP 协议:简单邮件传输协议,用于发送邮件的协议。 POP3 协议:负责邮件接收的协议。 | 1. HTTP 3.0 版本使用的是基于 UDP 的 QUIC 协议。<br>2. DHCP 协议:动态主机配置协议,动态配置 IP 地址。<br>3. DNS:域名解析系统,将域名转变为机器可读的 IP 地址。 总结成表格 |
# 前言
TCP (Transmission Control Protocol) 和 UDP (User Datagram Protocol) 是两种不同的网络传输协议。
# 什么是 TCP?
TCP 是一种面向连接的协议,它在传输数据之前会建立一条专用的通信连接。这意味着在数据传输过程中,两台计算机之间会有一条稳定的数据传输通道。因此,TCP 可以保证数据传输的可靠性,但会带来一定的延迟
# TCP 的协议格式
-
16 位源端口号和 16 位目的端口号: 表⽰数据是从哪个进程来,到哪个进程去;
-
32 位序号: 发送数据每个字节都有一个序号
-
32 位确认序号: 接收方会给出一个确认序号
-
4 位数据偏移: 这个字段是表示 TCP 数据报的报头有多大。
-
4 位可表示 0 - 15,单位为 “4 个字节”,由此得出 TCP 数据报报头最大 60 字节,报头中字段比特位明确,但选项和数据大小未给出,且选项在报头内,其最多可表达 40 字节数据。TCP 数据报整个报长在协议中没有规定
-
保留(6 位): 这个部分是留白,里面没有任何东西,是设计师预留出的给未来可能出现的功能的位置,
-
6 个标志位:
URG(Urgent): 紧急指针是否有效
ACK(Acknowledgment): 确认号是否有效。
PSH(Push): 提⽰接收端应⽤程序⽴刻从 TCP 缓冲区把数据读⾛
RST(Reset): 对⽅要求重新建⽴连接;我们把携带 RST 标识的称为复位报⽂段
SYN(Synchronization): 请求建⽴连接;我们把携带 SYN 标识的称为同步报⽂段。
FIN(Finish): 通知对⽅,本端要关闭了,我们称携带 FIN 标识的为结束报⽂段
- 16 位检验和: 发送端填充,CRC 校验。接收端校验不通过,则认为数据有问题。此处的检验和不光包含
TCP ⾸部,也包含 TCP 数据部分.
- 16 位紧急指针: 标识哪部分数据是紧急数据;
- 选项: Optional(可选项),可以自定义的勾选某些功能
# TCP 的十个核心机制
TCP 最核心的机制就是可靠传输
而实现可靠传输就时依靠确认应答机制来实现的,其中超时重传是对确认应答的重要补充。
# 1. 确认应答机制
应答的数据被称为应答报文
TCP 会给发送数据的每个字节编上序列号。发送端发送 TCP 数据报时,其载荷字节有相应编号,接收端收到后,根据数据报中的序号进行业务处理,然后将该序号加 1 作为确认序号,并把 ACK 标志位设为 1 返回给发送端。
也就是 TCP 通过对发送数据字节编号,接收端依据序号处理并返回加 1 后的确认序号及 ACK=1 给发送端。
返回的确认序号有两层含义
- 告诉发送端这个序列号之前的数据我已经全部接收了
- 请发送端下次发送数据时,从这个序号列开始发送
# 2. 超时重传
在传输过程中可能出现丢包这种情况
主机 A 将数据发送给主机 B 后,等待主机 B 的确认应答
当一段时间后还没有收到主机 B 的确认应答消息,此时主机 A 就会重新发送。
那么主机 A 是如何判断是否收到确认应答的呢?
这就是上面提到的应答报文中的标志位 ACK,主机 A 通过是否收到了 “ACK” 来判断是否收到了应答,如果一段时间内都没有收到 ACK 那么就认为是发生了丢包,进行重新发送。
但是还有个问题,就是 ACK 会不会也可能丢失了呢?
当时是会的
如上图就是 ACK 丢失的情况,那按照图中的显示,主机 B 就会收到两份相同的数据,这样的情况肯定不能允许存在的。那么 TCP 怎么处理呢?TCP 接收方这边会对接收的数据按照序列号来进行去重。
在 TCP 重复传输 \ 重复接收是无所谓的,但会保证在应用层不会读取到重复的数据。
上面了解了超时重传的机制,那么超时重传的时间间隔是多少呢?
这个时间不是一个固定值,是会随着重传次数的增加而变长,
当时间达到一定阈值,就会重置连接。触发一个” 复位报文 “来进行尝试重连
但是当网络出现严重的故障时,RST 也无法触发重置,只能断开连接(通信双方清除对方的数据,例如端口号、IP 地址等)
总结
-
TCP 实现可靠传输的方式:
-
发送方发送数据时对字节编号,编号连续自增,TCP 报头序号存储第一个字节序号。
-
接收方接收全部数据后,按接收到的序号 +1 生成确认序列,该确认序号有两个作用:表明此序号之前的数据已收到,以及告知接下来应发送从该确认序号开始的数据。同时将报头中 ACK 标识符的 bit 位改为 1,生成应答报文返回给发送方。
-
通信中丢包的处理:
-
TCP 采用超时重传机制,发送方未在规定时间内收到接收端应答报文时,会重新传输数据报。
-
每次重传的时间间隔会变长,到达一定阈值后,尝试重置连接。
-
重置连接细节:
-
将报头中的 RST 标志位的 bit 位改为 1 进行重置连接。
-
发送方和接收方会清除互相的信息(如端口号、IP 地址等)。
-
通信中重复数据的处理:
-
TCP 有接收缓冲区(类似带有优先级的阻塞队列),数据到达进入缓冲区,应用程序 read 时将数据从缓冲区删除。
-
TCP 接收在缓冲区按序列号对数据去重。
-
出现重复数据的原因:
-
发送方无法分辨是数据丢了还是 ACK 丢了,若 ACK 丢了,就会收到重复的数据。
# 3. 滑动窗口
在日常的业务场景下有时候会处理大量请求,如果再通过一条条发送接受的话,效率就会非常低,所以这时候就需要滑动窗口这样的机制了
- 窗口大小指的是无需得到 ACK 应答就能发送数据的最大值,图中的窗口大小是 2500 个字节(五个段)
- 当一个段接收到 ACK 后,窗口就会向后移动,然后发送第六个段的数据
- 操作系统内核开辟了发送缓冲区来记录当前有哪些数据还没有应答,应答了的数据就会从缓冲区中删除。
- 窗口越大,传输的数据就越多,网络的吞吐率就越高。
但是滑动窗口就不会丢包了么?
也会丢包,但是针对不同情况的影响不同
- 丢的是 ACK 包: 不影响,因为后续的应答数据报的确认序列会告诉进程,这个序列号之前的数据,都已经接收了。
- 丢的是 TCP 数据报: 有影响
- 假设窗口是 501 - 2001,若其中 501 - 1000 的数据报丢失。
- 接收端因未收到 501 - 1000 的数据报,会一直向发送端发送同一个应答数据报,要求下一个传输的数据报从 501 开始。
- 发送端连续收到这样的同一个应答数据报时,会重新发送 501 - 1000 的数据报。
- 接收端接收到 501 - 1000 的数据报后,继续执行。因操作系统内核有接收缓冲区,正常数据报会存于其中,处理完异常情况后,会依据缓冲区里的数据执行正常业务的应答数据报。
上面的处理方式被称为快速重传
** 滑动窗口有什么意义呢?
**TCP 为了保证可靠性,牺牲了很多的效率,滑动窗口就是为了弥补效率的牺牲,而采取的一种办法。
但是即使采取了措施,效率还是没有 UDP 快。
# 4. 流量控制
流量控制其实是滑动窗口的一个控制窗口大小的补充
因为接收端处理数据的速度是有限的,如果发送太快,接受端的数据还没处理就会导致接收端的缓冲区溢出,就有可能导致发生丢包,然后引起丢包重传等一系列问题
因此 TCP 支持根据接受端的处理能力来决定发送端的发送速度,这个机制就叫做流量控制(FlowControl)
# 5. 阻塞控制
和流量控制一样,都是为了辅助滑动窗口使用的
数据在网络的传输中,会经过很多网络结点。传输的速度就会受到这些结点的限制。
为了探寻传输数据的的最高效率,引入了阻塞控制
具体的工作流程如下:
- 最开始按照小的速度,小的窗口来发送数据
- 如果没有丢包,就加大速度,增大窗口,继续发送
- 增加到一定程度,出现了丢包现象,就立即减小速度,缩小窗口
- 当没有丢包情况出现后,就继续加大速度,增大窗口
- 上述操作持续进行,直到找到一个阈值。
上面讲到的流量控制也会改变窗口的大小,那么流量控制的窗口和阻塞控制的窗口选择哪个呢?
按照小的来
阻塞控制的窗口变化也是有相应的规律的
- 慢开始: 先以小的窗口传输数据,主要是检测通信路径是否通畅。
- 扩大窗口①:以指数的形式来扩大窗口。
- 扩大窗口②:到达某个阈值,就开始线性扩大窗口
- 缩小窗口:
①:窗口直接缩小到 0,再重复上述流程,
②:窗口缩小一半,然后线性的增长窗口。
# 6. 延迟应答
-
接收方接收到数据后不立即返回 ACK,而是隔一段时间再返回,可提高传输速率。
-
窗口越大,网络吞吐量越大,网络传输速度越快。
-
接收方接收数据后处理数据需要时间,延迟应答的这段时间可用于处理数据。处理完数据后,缓冲区空闲窗口变大,通过流量控制响应反馈,使传输速度变快。
-
延迟应答机制在特殊情况下可将四次挥手合并成三次挥手,一般情况仍为四次挥手。
-
延迟应答的时间的规划
-
按照一定的时间来应答,一般是 200ms
-
按照收到的数据报个数来应答,一般是两个包
# 7. 捎带应答
- 捎带应答:在满足业务逻辑的情况下,将两个或几个数据报的内容合并在一起。
- 示例:三次挥手中,将 ACK 报文和 SYN 报文合并。
- 意义:提高效率,减轻服务器压力。一次数据传输需经过层层封装和分用,合并操作可减少工作量 。
# 8. 粘包问题
-
粘包问题实质:粘包问题粘的是应用层的数据报。
-
出现原因:
-
TCP 协议报头不像 UDP 协议报头有报文长度属性字段,无法确定数据报长度进行分割。
-
传输层角度,TCP 报文按序号排放在缓冲区;应用层角度,看到的是连续字节数据,应用程序难以确定完整数据包的起止位置。
-
避免方法:
-
使用分割符:定义任意字符作为分隔符,如用空格分割数据包。
-
约定包的长度:在发送数据包前,一同发送数据包的长度,以此确定包的结束位置 。
# 9. 异常情况
- 一个进程崩溃:进程终止会释放文件描述符,可发送 FIN,与正常关闭无区别。操作系统内核回收释放对应 PCB 及文件描述符表(相当于 close),会正常完成四次挥手。
- 主机正常关机:操作系统先强制结束所有进程,正常进行四次挥手,但不一定完成。发送 FIN 后若未收到 ACK 或收到 ACK 后进程结束,对方 FIN 会重复传送几次,重传无果后会删除对方信息。
- 主机电源断开:
- 接收端电源断开:发送端数据无 ACK,触发超时重传,重传几次后发送复位报文 RST,无响应则删除接收端信息。
- 发送端电源断开:接收方一段时间未收到数据会触发心跳包,多次发送无回复,会认为发送方进程结束并删除其信息。
- 网络断开:本质与主机电源断开情况类似 。
# 10. 连接管理(三次握手、四次挥手)
放在最后讲,因为这个面试重点。QAQ
建立连接:三次握手
断开连接:四次挥手
握手:发送一个不含业务数据的数据报,不起到任何业务的作用,只是建立连接。
# 三次握手
-
服务端和客户端交互过程:
-
双方各自给对方发送一个 SYN。
-
双方各自给对方返回一个 ACK,实际共四次交互。
-
特殊合并情况:
-
中间的 ACK 和 SYN 可合并成一个数据报。
-
此合并由内核完成,当收到客户端的 SYN 同步报文后,内核立即在同一时刻生成 ACK 和 SYN。
-
合并的数据报中,ACK 的 bit 为 1,SYN 的 bit 也为 1。
** 可以缩减为两次握手吗?
** 不可以,服务器对于通信双方的接收能力和发送能力的验证没能完成。
** 那么四次交互不是更直观吗?
** 这是因为三次的效率比四次要高。
在数据的传输过程中,要经过层层的封装和分用,多一次而带来的消耗就会很大。
# 三次握手的意义
- 在数据传输前,先确保通信链路是否通畅
- 通过三次握手,来确认通信双方的接收和发送功能都是正常的。
- 还需要协商一些必要的参数。有些参数不是单方面可以确定的,需要双方商量来决定。
# 三次握手协商
- 三次握手协商的作用:TCP 通信使用的序号通过三次握手协商得出。
- 序号特点:第一次和第二次连接协商出的起始序号通常差别很大。
- 避免问题:防止数据报在网络中长时间游转,在通信双方断开又重新连接(业务更替)后才到达接收端。接收端会根据序号差异判断,若差异过大则丢弃数据报,避免上一次业务逻辑影响本次业务 。
# 四次挥手
客户端和服务端都可以先发起 FIN(结束报文)
假设客户端先发起
和三次握手很相似,但是四次挥手为什么中间的两次操作不能合并?
四次挥手的 FIN 和 ACK 报文可以合并吗?
在特殊情况下是可以的,但一般来说是不可以的。
- 一般情况
当收到 FIN 报文时,内核直接就返回 ACK 报文,而 FIN 报文是由应用程序来控制的(socket.close),不是同一时刻,所有不能合并。
三次握手是因为 SYN 和 ACK 都是由内核控制的,所以可以合并。
- 特殊情况
TCP 有一个延时应答机制,在回复 ACK 数据报时,不是立即回复,而是等待一段时间,这时 ACK 和 FIN 就可以合并成一个报文了。
在服务器看到大量的 CLOSE_WAIT,可能是什么原因?
- close 未调用
- close 调用不及时
- LISTEN - 侦听来自远方 TCP 端口的连接请求;
- SYN-SENT - 在发送连接请求后等待匹配的连接请求;
- SYN-RECEIVED - 在收到和发送一个连接请求后等待对连接请求的确认;
- ESTABLISHED - 代表一个打开的连接,数据可以传送给用户;
- FIN-WAIT-1 - 等待远程 TCP 的连接中断请求,或先前的连接中断请求的确认;
- FIN-WAIT-2 - 从远程 TCP 等待连接中断请求;
- CLOSE-WAIT - 等待从本地用户发来的连接中断请求;
- CLOSING - 等待远程 TCP 对连接中断的确认;
- LAST-ACK - 等待原来发向远程 TCP 的连接中断请求的确认;
- TIME-WAIT - 等待足够的时间以确保远程 TCP 接收到连接中断请求的确认;
- CLOSED - 没有任何连接状态;
为什么会有 TIME_WAI?
-
当服务器给客户端发送 FIN 后:
-
客户端不能立即释放 TCP 连接。原因是客户端还未发送 ACK 给服务器,若服务器一段时间没收到 ACK 就会重传 FIN,重传后客户端仍需将 ACK 返回给服务器,这需要服务器的端口号等信息。
-
在一定时间段内,客户端若没有收到服务器重传的 FIN,说明 ACK 已被服务器接收。
# 什么是 UDP?
UDP(User Datagram Protocol,用户数据报协议)是一种网络通信协议,它属于传输层的协议。是一个简单的、面向无连接的协议。UDP 用于将数据从一个应用程序发送到另一个应用程序,并在此过程中不提供可靠的数据传输保障。UDP 支持一对一、一对多、多对多的交互通信。
- UDP 是不具有可靠性的协议,细微处理交给上层应用完成。
- 使用 UDP 时,能确保发送消息的大小,发送端发送特定长度消息,接收端也以相同长度接收,消息长度数据会一同发送,无需在消息中设置表示长度或间隔的字段。
- UDP 不具备可靠传输,消息在网络传输途中可能丢失,接收端可能收不到消息,应用有时会按需进行重发处理 。
UDP 不提供复杂的控制机制,利用 IP 提供面向「无连接」的通信服务。
就是说 UDP 是依赖于底层的 IP 协议来进行数据传输。IP 提供了基本的无连接数据传输服务,UDP 在此基础上构建,只是增加了端口号等基本的传输控制功能,但不提供额外的可靠性或连接管理。
UDP 面向无连接,能随时发送数据,处理简单高效,常用于以下方面:
- 包总量较少的通信,如 DNS、SNMP 等。
- 视频、音频等多媒体通信(即时通信)。
- 广播通信(广播、多播)。
- 限定于 LAN 等特定网络中的应用通信。
总结
- 网络套接字编程接口处于应用层和传输层之间,是操作系统提供的系统调用接口,有
socket()
、bind()
、sendto()
、recvfrom()
等标准函数供应用程序进行网络通信。 - UDP 由操作系统内核实现,是协议栈一部分,其数据报的发送和接收等功能由操作系统负责。
- 操作系统内核提供包含多种网络协议(如 IP、TCP、UDP 等)的完整网络协议栈,管理网络通信底层细节。
- 网络功能是操作系统的一部分,通过网络套接字接口让应用程序使用内核级网络功能。
- 网络套接字编程接口是应用层与操作系统的桥梁,使应用程序能利用 TCP、UDP 等底层协议,HTTP 等高层协议基于此实现功能,分层设计让网络编程灵活高效。
# UDP 的协议格式
UDP 数据段的长度为 16 位,也就是说 UDP 能传输的最大长度是 64K(包括 UDP 首部字段)。
若传输的数据超过 64K,就需要在应用层手动分包,多次发送,并在接收端手动拼装。
校验和(Checksum):用于检测数据在传输过程中是否被篡改或损坏。它是 UDP 首部和数据部分的 16 位字的反码和。这个字段在某些实现中可能是可选的(可以为 0),但在 IPv6 中是强制的。
UDP 报头在内核中的实现:
#include <linux/types.h> | |
struct udphdr { | |
u16 | |
source; | |
dest;u16 | |
len;u16 | |
u16check; | |
}; |
这个结构体 UDPhdr 用于表示 UDP(用户数据报协议)报头,它通常用于网络编程中。下面是这个结构体中各个字段的含义:
- source:源端口号,占 16 位,表示发送方的端口号。
- dest:目的端口号,占 16 位,表示接收方的端口号。
- len:UDP 长度,占 16 位,包括 UDP 头部和 UDP 数据的总长度。
- check:校验和,占 16 位,用于检测 UDP 数据在传输过程中是否出现错误。
这个结构体通常用于原始套接字编程,或者在网络协议的实现中。
# UDP 报文的解包和分用
-
UDP 报文解包过程:
-
接收数据报:网络层把接收到的 IP 数据报传给传输层。
-
解析 UDP 首部:传输层解析 UDP 数据报前 8 个字节,获取源端口、目的端口、报文长度和校验和。
-
校验和验证:计算校验和验证数据报完整性,不匹配则丢弃。
-
提取数据部分:从 UDP 数据报中提取实际数据部分交给上层应用。
-
UDP 分用过程:
-
检查目的端口:用解析出的目的端口号确定数据报应交付的应用程序。
-
查找对应的进程:操作系统依据端口号到进程的映射表,通过目的端口号找到相应进程。
-
传递数据:将数据报内容传递给相应应用程序。
-
UDP 报头特点:
-
UDP 报头包含四个字段,每个字段长度 16 位,共 8 字节,采用定长报头。
-
读取报文时,读完前 8 个字节后剩余的都是有效载荷。
# UDP 面向数据报的特点
UDP 传输过程类似寄信,具有以下特性:
-
无连接性:
-
UDP 无连接,发送方和接收方无需建立或维护连接。
-
每个数据报文独立,不依赖前后数据报,适合快速传输的应用,如实时视频流、在线游戏等。
-
数据报独立性与无序性:
-
每个数据报是独立单元,相互间无顺序关系,某数据报的问题不影响其他数据报传输。
-
不保证数据报按发送顺序到达接收端,接收端可能收到乱序数据,应用程序需自行处理顺序问题。
-
不可靠:
-
无确定机制和重传机制,网络故障导致数据无法发送时,UDP 协议层不给应用层返回错误信息。
-
数据报在传输中丢失或损坏,UDP 不会自动重传,适用于高实时性但对数据可靠性要求不高的场景 。
如何理解 UDP 是面向数据报的?
UDP 是无连接、面向数据报的传输层协议,设计高效,适用于需快速传输但无需可靠性保证的应用。UDP 客户与服务间无长期关系,例如 UDP 客户可用同一套接字先后向不同服务器发送数据报,UDP 服务器也可用同一套接字从多个不同客户接收数据报 。
UDP 面向数据报的实现包含以下环节:
-
数据报传输:
-
每个数据报在 UDP 中从发送端到接收端独立传输。
-
发送端把数据封装成 UDP 数据报,经网络层(IP 层)发至接收端。
-
接收端接收数据报后,提取 UDP 首部信息和数据部分,将数据交相应应用程序处理。
-
报文解包:
-
在接收端,解析 UDP 首部获取源端口、目的端口、数据长度和校验和等信息。
-
提取数据部分,依据目的端口号将数据传递给相应应用程序。
-
分用:
-
接收端通过目的端口号确定接收数据报的应用程序,此方式称为分用。
-
操作系统维护端口号到应用程序的映射表,通过查表将数据报传递给正确的应用程序。
UDP 被称为面向数据报的协议,原因如下
- 独立的数据报:每个 UDP 数据报相互独立,可独立处理和传输,不依赖其他数据报状态。
- 无连接和无状态:不维护连接状态,不跟踪数据报传输状态,传输过程独立,无连接建立、维护或终止的额外开销。
- 简单的首部:首部简洁,仅含必要信息,数据报处理和解析速度快。
- 不保证可靠性:不保证数据报可靠传输、不丢失、按序到达,每个数据报处理独立,不依赖前后数据报传输状态。
# UDP 输入输出
-
UDP 处理流程:一端的 UDP 给用户数据报安上 8 字节首部构成 UDP 数据报,然后传递给 IP 层。
-
套接字发送缓冲区:
-
虚线框表示的 UDP 套接字发送缓冲区实际不存在,每个 UDP 套接字都有发送缓冲区大小,它是可写到该套接字的 UDP 数据报大小上限。
-
若应用进程写的 UDP 数据报大于套接字发送缓冲区大小,内核返回进程 EMSGSIZE 错误。
-
UDP 与发送缓冲区的关系:
-
UDP 不可靠,不必保存应用进程数据副本,没有像 TCP 一样真正的发送缓冲区。
-
调用 sendto 直接交给内核,由内核将数据传给网络层协议进行传输。
-
UDP 发送缓冲区数据移除特点:数据发送成功后,会立即从缓冲区中移除,不像 TCP 需等待接收方确认。
发送缓冲区(Send Buffer)是一个内核空间中的缓冲区,专门用于临时存储应用程序准备发送的数据。它的作用是在网络协议栈中不同层次之间传递数据时,确保数据能够有序且可靠地传输。
应用进程的数据在沿协议栈向下传递时,通常被复制到某种格式的一个内核缓冲区中。当数据通过协议栈传递并成功发送后,数据链路层完成了数据的传输任务,此时该数据的副本在发送缓冲区中的存在已经没有意义。因此,内核会将发送缓冲区中的数据副本丢弃,以便释放内存资源给后续需要发送的数据。
简单来说,发送缓冲区存在的意义就是:接收方来不及接收了,我们暂时把它放在缓冲区保存,等对方来得及接收了,有接收能力了再发送给对方。
UDP 套接字接收缓冲区
- UDP 给特定套接字排队的 UDP 数据报数目受限于该套接字接收缓冲区大小。
- 缓冲区无法保证收到 UDP 报的顺序与发送顺序一致。
- 若缓冲区满,新到达的 UDP 数据将被丢弃。
UDP 没有发送缓冲区
- UDP 是无连接协议,不提供可靠数据传输保证。
- 应用程序调用 sendto 函数时,UDP 直接将数据传递给网络层,不像 TCP 在发送缓冲区排队等待确认。
- UDP 不进行拥塞控制,无重传机制,发送操作通常立即返回,即便数据报可能未完全发送到网络。
UDP 接收缓冲区(再次强调)
- 存在于内核中,用于暂存从网络层接收的 UDP 数据报。
- 因 UDP 协议性质,不能保证数据报接收顺序与发送顺序一致,受网络延迟、路由差异等影响。
- 缓冲区满时新到达数据报可能被丢弃,UDP 协议不通知发送方数据报丢失,需应用程序自行处理 。
应用注意事项:
- 应用程序在使用 UDP 时应该考虑到数据报可能会丢失、重复或乱序。
- 对于需要可靠传输的应用,开发者需要在应用层实现额外的机制,如确认、重传等。
- 应用程序还应该考虑到接收缓冲区的大小,以避免在高速网络环境中因为缓冲区溢出而丢失数据。
UDP 不是全双工的,但是可以实现全双工。
UDP 设计目标为简单和低开销,全双工通信因需更多控制信息、状态维护以及处理流量控制等复杂问题,与 UDP 设计目标相悖,且若 UDP 采用全双工会增加网络堆栈资源使用,有违其减少资源使用的设计意图,所以 UDP 仅提供数据报文发送和接收功能,将复杂责任交予应用程序。此外,UDP 协议中 connect 会改变套接字原绑定的目标地址和端口号,不同于 TCP,它不与目标地址握手或建立连接,只是设置默认目的地址。
UDP 服务器接收数据的方式,以及是否能够同时接收来自多个客户端的数据
UDP 是无连接协议,不保证数据可靠传输,无需在数据传输前建立连接。
-
接收数据情况:
-
服务器使用 recvfrom 系统调用等待接收数据,该调用会阻塞当前线程直至收到客户端数据。
-
收到数据后,服务器记录日志,处理后将数据发回客户端。
-
UDP 支持多播和广播:
-
广播:服务器可在本地网络向所有客户端发送数据,客户端也能通过广播向服务器发消息。
-
多播:服务器可订阅特定多播组,加入组的客户端能向组内发消息,服务器接收组内所有客户端数据。
-
这使 UDP 不仅能单播与多客户端通信,还能通过广播、多播同时处理多客户端数据报。
-
多个客户端同时发送数据:
-
UDP 无连接,服务器无需为每个客户端维持单独连接,能用相同 recvfrom () 函数接收不同客户端数据包。
-
多个客户端几乎同时发送数据时,由操作系统内核网络栈处理,服务器可能收到不同客户端数据。
-
注意点:
-
UDP 不保证可靠传输,网络不佳或数据报丢失时,服务器可能收不到某些客户端数据。
-
recvfrom 每次调用只处理一个数据报,多个数据报同时到达会在内核队列中排队等待处理。
-
总结:UDP 服务器能同时接收多个客户端数据,原因是 UDP 支持多播和广播,且单个套接字可接收不同发送者的数据报。