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 的协议格式

image.png

  • 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. 确认应答机制

image.png

应答的数据被称为应答报文

image.png

TCP 会给发送数据的每个字节编上序列号。发送端发送 TCP 数据报时,其载荷字节有相应编号,接收端收到后,根据数据报中的序号进行业务处理,然后将该序号加 1 作为确认序号,并把 ACK 标志位设为 1 返回给发送端。

也就是 TCP 通过对发送数据字节编号,接收端依据序号处理返回加 1 后的确认序号及 ACK=1 给发送端。

返回的确认序号有两层含义

  1. 告诉发送端这个序列号之前的数据我已经全部接收了
  2. 请发送端下次发送数据时,从这个序号列开始发送

# 2. 超时重传

在传输过程中可能出现丢包这种情况
image.png

主机 A 将数据发送给主机 B 后,等待主机 B 的确认应答
当一段时间后还没有收到主机 B 的确认应答消息,此时主机 A 就会重新发送。

那么主机 A 是如何判断是否收到确认应答的呢?

这就是上面提到的应答报文中的标志位 ACK,主机 A 通过是否收到了 “ACK” 来判断是否收到了应答,如果一段时间内都没有收到 ACK 那么就认为是发生了丢包,进行重新发送。

但是还有个问题,就是 ACK 会不会也可能丢失了呢?

当时是会的

image.png

如上图就是 ACK 丢失的情况,那按照图中的显示,主机 B 就会收到两份相同的数据,这样的情况肯定不能允许存在的。那么 TCP 怎么处理呢?TCP 接收方这边会对接收的数据按照序列号来进行去重。

在 TCP 重复传输 \ 重复接收是无所谓的,但会保证在应用层不会读取到重复的数据。

上面了解了超时重传的机制,那么超时重传的时间间隔是多少呢?

这个时间不是一个固定值,是会随着重传次数的增加而变长,
当时间达到一定阈值,就会重置连接。触发一个” 复位报文 “来进行尝试重连

image.png

但是当网络出现严重的故障时,RST 也无法触发重置,只能断开连接(通信双方清除对方的数据,例如端口号、IP 地址等)

总结

  • TCP 实现可靠传输的方式:

  • 发送方发送数据时对字节编号,编号连续自增,TCP 报头序号存储第一个字节序号。

  • 接收方接收全部数据后,按接收到的序号 +1 生成确认序列,该确认序号有两个作用:表明此序号之前的数据已收到,以及告知接下来应发送从该确认序号开始的数据。同时将报头中 ACK 标识符的 bit 位改为 1,生成应答报文返回给发送方。

  • 通信中丢包的处理:

  • TCP 采用超时重传机制,发送方未在规定时间内收到接收端应答报文时,会重新传输数据报。

  • 每次重传的时间间隔会变长,到达一定阈值后,尝试重置连接。

  • 重置连接细节:

  • 将报头中的 RST 标志位的 bit 位改为 1 进行重置连接。

  • 发送方和接收方会清除互相的信息(如端口号、IP 地址等)。

  • 通信中重复数据的处理:

  • TCP 有接收缓冲区(类似带有优先级的阻塞队列),数据到达进入缓冲区,应用程序 read 时将数据从缓冲区删除。

  • TCP 接收在缓冲区按序列号对数据去重。

  • 出现重复数据的原因:

  • 发送方无法分辨是数据丢了还是 ACK 丢了,若 ACK 丢了,就会收到重复的数据。

# 3. 滑动窗口

在日常的业务场景下有时候会处理大量请求,如果再通过一条条发送接受的话,效率就会非常低,所以这时候就需要滑动窗口这样的机制了

image.png

  • 窗口大小指的是无需得到 ACK 应答就能发送数据的最大值,图中的窗口大小是 2500 个字节(五个段)
  • 一个段接收到 ACK 后,窗口就会向后移动,然后发送第六个段的数据
  • 操作系统内核开辟了发送缓冲区来记录当前有哪些数据还没有应答,应答了的数据就会从缓冲区中删除
  • 窗口越大,传输的数据就越多,网络的吞吐率就越高。

image.png

但是滑动窗口就不会丢包了么?

也会丢包,但是针对不同情况的影响不同

  • 丢的是 ACK 包: 不影响,因为后续的应答数据报的确认序列会告诉进程,这个序列号之前的数据,都已经接收了。
  • 丢的是 TCP 数据报: 有影响
  1. 假设窗口是 501 - 2001,若其中 501 - 1000 的数据报丢失。
  2. 接收端因未收到 501 - 1000 的数据报,会一直向发送端发送同一个应答数据报,要求下一个传输的数据报从 501 开始。
  3. 发送端连续收到这样的同一个应答数据报时,会重新发送 501 - 1000 的数据报。
  4. 接收端接收到 501 - 1000 的数据报后,继续执行。因操作系统内核有接收缓冲区,正常数据报会存于其中,处理完异常情况后,会依据缓冲区里的数据执行正常业务的应答数据报。

上面的处理方式被称为快速重传

** 滑动窗口有什么意义呢?
**TCP 为了保证可靠性,牺牲了很多的效率,滑动窗口就是为了弥补效率的牺牲,而采取的一种办法。
但是即使采取了措施,效率还是没有 UDP 快。

# 4. 流量控制

流量控制其实是滑动窗口的一个控制窗口大小的补充

因为接收端处理数据的速度是有限的,如果发送太快,接受端的数据还没处理就会导致接收端的缓冲区溢出,就有可能导致发生丢包,然后引起丢包重传等一系列问题

因此 TCP 支持根据接受端的处理能力来决定发送端的发送速度,这个机制就叫做流量控制(FlowControl)

image.png

image.png

# 5. 阻塞控制

和流量控制一样,都是为了辅助滑动窗口使用的

数据在网络的传输中,会经过很多网络结点。传输的速度就会受到这些结点的限制。
为了探寻传输数据的的最高效率,引入了阻塞控制

具体的工作流程如下:

  • 最开始按照小的速度,小的窗口来发送数据
  • 如果没有丢包,就加大速度,增大窗口,继续发送
  • 增加到一定程度,出现了丢包现象,就立即减小速度,缩小窗口
  • 当没有丢包情况出现后,就继续加大速度,增大窗口
  • 上述操作持续进行,直到找到一个阈值。

上面讲到的流量控制也会改变窗口的大小,那么流量控制的窗口和阻塞控制的窗口选择哪个呢?

按照小的来

阻塞控制的窗口变化也是有相应的规律的

image.png

  1. 慢开始: 先以小的窗口传输数据,主要是检测通信路径是否通畅。
  2. 扩大窗口①:以指数的形式来扩大窗口。
  3. 扩大窗口②:到达某个阈值,就开始线性扩大窗口
  4. 缩小窗口
    ①:窗口直接缩小到 0,再重复上述流程,
    ②:窗口缩小一半,然后线性的增长窗口。

# 6. 延迟应答

  • 接收方接收到数据后不立即返回 ACK,而是隔一段时间再返回,可提高传输速率。

  • 窗口越大,网络吞吐量越大,网络传输速度越快。

  • 接收方接收数据后处理数据需要时间,延迟应答的这段时间可用于处理数据。处理完数据后,缓冲区空闲窗口变大,通过流量控制响应反馈,使传输速度变快。

  • 延迟应答机制在特殊情况下可将四次挥手合并成三次挥手,一般情况仍为四次挥手。

  • 延迟应答的时间的规划

  • 按照一定的时间来应答,一般是 200ms

  • 按照收到的数据报个数来应答,一般是两个包

# 7. 捎带应答

  • 捎带应答:在满足业务逻辑的情况下,将两个或几个数据报的内容合并在一起。
  • 示例:三次挥手中,将 ACK 报文和 SYN 报文合并。
  • 意义:提高效率,减轻服务器压力。一次数据传输需经过层层封装和分用,合并操作可减少工作量 。

# 8. 粘包问题

  • 粘包问题实质:粘包问题粘的是应用层的数据报。

  • 出现原因

  • TCP 协议报头不像 UDP 协议报头有报文长度属性字段,无法确定数据报长度进行分割。

  • 传输层角度,TCP 报文按序号排放在缓冲区;应用层角度,看到的是连续字节数据,应用程序难以确定完整数据包的起止位置。

  • 避免方法

  • 使用分割符:定义任意字符作为分隔符,如用空格分割数据包。

  • 约定包的长度:在发送数据包前,一同发送数据包的长度,以此确定包的结束位置 。

# 9. 异常情况

  1. 一个进程崩溃:进程终止会释放文件描述符,可发送 FIN,与正常关闭无区别。操作系统内核回收释放对应 PCB 及文件描述符表(相当于 close),会正常完成四次挥手。
  2. 主机正常关机:操作系统先强制结束所有进程,正常进行四次挥手,但不一定完成。发送 FIN 后若未收到 ACK 或收到 ACK 后进程结束,对方 FIN 会重复传送几次,重传无果后会删除对方信息。
  3. 主机电源断开
  • 接收端电源断开:发送端数据无 ACK,触发超时重传,重传几次后发送复位报文 RST,无响应则删除接收端信息。
  • 发送端电源断开:接收方一段时间未收到数据会触发心跳包,多次发送无回复,会认为发送方进程结束并删除其信息。
  1. 网络断开:本质与主机电源断开情况类似 。

# 10. 连接管理(三次握手、四次挥手)

放在最后讲,因为这个面试重点。QAQ

建立连接:三次握手

断开连接:四次挥手

握手:发送一个不含业务数据的数据报,不起到任何业务的作用,只是建立连接。

# 三次握手

image.png

  • 服务端和客户端交互过程

  • 双方各自给对方发送一个 SYN。

  • 双方各自给对方返回一个 ACK,实际共四次交互。

  • 特殊合并情况

  • 中间的 ACK 和 SYN 可合并成一个数据报。

  • 此合并由内核完成,当收到客户端的 SYN 同步报文后,内核立即在同一时刻生成 ACK 和 SYN。

  • 合并的数据报中,ACK 的 bit 为 1,SYN 的 bit 也为 1。

** 可以缩减为两次握手吗?
** 不可以,服务器对于通信双方的接收能力和发送能力的验证没能完成。
** 那么四次交互不是更直观吗?
** 这是因为三次的效率比四次要高。
在数据的传输过程中,要经过层层的封装和分用,多一次而带来的消耗就会很大。

# 三次握手的意义

  1. 在数据传输前,先确保通信链路是否通畅
  2. 通过三次握手,来确认通信双方的接收和发送功能都是正常的。
  3. 还需要协商一些必要的参数。有些参数不是单方面可以确定的,需要双方商量来决定。

# 三次握手协商

  • 三次握手协商的作用:TCP 通信使用的序号通过三次握手协商得出。
  • 序号特点:第一次和第二次连接协商出的起始序号通常差别很大。
  • 避免问题:防止数据报在网络中长时间游转,在通信双方断开又重新连接(业务更替)后才到达接收端。接收端会根据序号差异判断,若差异过大则丢弃数据报,避免上一次业务逻辑影响本次业务 。

# 四次挥手

客户端和服务端都可以先发起 FIN(结束报文)

假设客户端先发起

image.png

和三次握手很相似,但是四次挥手为什么中间的两次操作不能合并?

四次挥手的 FIN 和 ACK 报文可以合并吗?

在特殊情况下是可以的,但一般来说是不可以的。

  • 一般情况

当收到 FIN 报文时,内核直接就返回 ACK 报文,而 FIN 报文是由应用程序来控制的(socket.close),不是同一时刻,所有不能合并。

三次握手是因为 SYN 和 ACK 都是由内核控制的,所以可以合并。

  • 特殊情况

TCP 有一个延时应答机制,在回复 ACK 数据报时,不是立即回复,而是等待一段时间,这时 ACK 和 FIN 就可以合并成一个报文了。

在服务器看到大量的 CLOSE_WAIT,可能是什么原因?

  1. close 未调用
  2. close 调用不及时

image.png

  1. LISTEN - 侦听来自远方 TCP 端口的连接请求;
  2. SYN-SENT - 在发送连接请求后等待匹配的连接请求;
  3. SYN-RECEIVED - 在收到和发送一个连接请求后等待对连接请求的确认;
  4. ESTABLISHED - 代表一个打开的连接,数据可以传送给用户;
  5. FIN-WAIT-1 - 等待远程 TCP 的连接中断请求,或先前的连接中断请求的确认;
  6. FIN-WAIT-2 - 从远程 TCP 等待连接中断请求;
  7. CLOSE-WAIT - 等待从本地用户发来的连接中断请求;
  8. CLOSING - 等待远程 TCP 对连接中断的确认;
  9. LAST-ACK - 等待原来发向远程 TCP 的连接中断请求的确认;
  10. TIME-WAIT - 等待足够的时间以确保远程 TCP 接收到连接中断请求的确认;
  11. 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 的协议格式

image.png

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 输入输出

image.png

  • UDP 处理流程:一端的 UDP 给用户数据报安上 8 字节首部构成 UDP 数据报,然后传递给 IP 层。

  • 套接字发送缓冲区

  • 虚线框表示的 UDP 套接字发送缓冲区实际不存在,每个 UDP 套接字都有发送缓冲区大小,它是可写到该套接字的 UDP 数据报大小上限。

  • 若应用进程写的 UDP 数据报大于套接字发送缓冲区大小,内核返回进程 EMSGSIZE 错误。

  • UDP 与发送缓冲区的关系

  • UDP 不可靠,不必保存应用进程数据副本,没有像 TCP 一样真正的发送缓冲区。

  • 调用 sendto 直接交给内核,由内核将数据传给网络层协议进行传输。

  • UDP 发送缓冲区数据移除特点:数据发送成功后,会立即从缓冲区中移除,不像 TCP 需等待接收方确认。

发送缓冲区(Send Buffer)是一个内核空间中的缓冲区,专门用于临时存储应用程序准备发送的数据。它的作用是在网络协议栈中不同层次之间传递数据时,确保数据能够有序且可靠地传输。

应用进程的数据在沿协议栈向下传递时,通常被复制到某种格式的一个内核缓冲区中。当数据通过协议栈传递并成功发送后,数据链路层完成了数据的传输任务,此时该数据的副本在发送缓冲区中的存在已经没有意义。因此,内核会将发送缓冲区中的数据副本丢弃,以便释放内存资源给后续需要发送的数据。

简单来说,发送缓冲区存在的意义就是:接收方来不及接收了,我们暂时把它放在缓冲区保存,等对方来得及接收了,有接收能力了再发送给对方。

UDP 套接字接收缓冲区

  1. UDP 给特定套接字排队的 UDP 数据报数目受限于该套接字接收缓冲区大小。
  2. 缓冲区无法保证收到 UDP 报的顺序与发送顺序一致。
  3. 若缓冲区满,新到达的 UDP 数据将被丢弃。

UDP 没有发送缓冲区

  1. UDP 是无连接协议,不提供可靠数据传输保证。
  2. 应用程序调用 sendto 函数时,UDP 直接将数据传递给网络层,不像 TCP 在发送缓冲区排队等待确认。
  3. UDP 不进行拥塞控制,无重传机制,发送操作通常立即返回,即便数据报可能未完全发送到网络。

UDP 接收缓冲区(再次强调)

  1. 存在于内核中,用于暂存从网络层接收的 UDP 数据报。
  2. 因 UDP 协议性质,不能保证数据报接收顺序与发送顺序一致,受网络延迟、路由差异等影响。
  3. 缓冲区满时新到达数据报可能被丢弃,UDP 协议不通知发送方数据报丢失,需应用程序自行处理 。

应用注意事项:

  • 应用程序在使用 UDP 时应该考虑到数据报可能会丢失、重复或乱序。
  • 对于需要可靠传输的应用,开发者需要在应用层实现额外的机制,如确认、重传等。
  • 应用程序还应该考虑到接收缓冲区的大小,以避免在高速网络环境中因为缓冲区溢出而丢失数据。

UDP 不是全双工的,但是可以实现全双工。

UDP 设计目标为简单和低开销,全双工通信因需更多控制信息、状态维护以及处理流量控制等复杂问题,与 UDP 设计目标相悖,且若 UDP 采用全双工会增加网络堆栈资源使用,有违其减少资源使用的设计意图,所以 UDP 仅提供数据报文发送和接收功能,将复杂责任交予应用程序。此外,UDP 协议中 connect 会改变套接字原绑定的目标地址和端口号,不同于 TCP,它不与目标地址握手或建立连接,只是设置默认目的地址。

UDP 服务器接收数据的方式,以及是否能够同时接收来自多个客户端的数据

UDP 是无连接协议,不保证数据可靠传输,无需在数据传输前建立连接。

  • 接收数据情况

  • 服务器使用 recvfrom 系统调用等待接收数据,该调用会阻塞当前线程直至收到客户端数据。

  • 收到数据后,服务器记录日志,处理后将数据发回客户端。

  • UDP 支持多播和广播

  • 广播:服务器可在本地网络向所有客户端发送数据,客户端也能通过广播向服务器发消息。

  • 多播:服务器可订阅特定多播组,加入组的客户端能向组内发消息,服务器接收组内所有客户端数据。

  • 这使 UDP 不仅能单播与多客户端通信,还能通过广播、多播同时处理多客户端数据报。

  • 多个客户端同时发送数据

  • UDP 无连接,服务器无需为每个客户端维持单独连接,能用相同 recvfrom () 函数接收不同客户端数据包。

  • 多个客户端几乎同时发送数据时,由操作系统内核网络栈处理,服务器可能收到不同客户端数据。

  • 注意点

  • UDP 不保证可靠传输,网络不佳或数据报丢失时,服务器可能收不到某些客户端数据。

  • recvfrom 每次调用只处理一个数据报,多个数据报同时到达会在内核队列中排队等待处理。

  • 总结:UDP 服务器能同时接收多个客户端数据,原因是 UDP 支持多播和广播,且单个套接字可接收不同发送者的数据报。

AI 助手
你好,我是小木
您可以尝试点击下方的快捷入口开启体验!