这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

传输层

本章是计算机网络中的重点,需熟练掌握TCP的滑动窗口机制、连接断开与建立、流量和拥塞控制。

学习思维导图

# 传输层

## 提供的服务

- 传输层功能
- 寻址和端口
- 无连接和面向连接服务

## UDP协议

- UDP数据报
- UDP校验

## TCP协议

- TCP段
- 连接管理
- 可靠传输
- 流量控制
- 拥塞控制

传输层功能

  1. 数据分段与重组:传输层将上层应用层提供的数据流划分为较小的数据段,以便在网络中传输。在接收端,传输层负责将这些数据段重新组装成完整的数据流,以交付给应用层。
  2. 端口标识与多路复用:传输层使用端口号来标识不同的应用程序或服务。当多个应用程序同时运行时,传输层可以将它们的数据段混合在一起传输,并在接收端根据端口号将数据分发给正确的应用程序,从而实现多路复用。
  3. 会话管理:传输层还可以支持会话管理,包括建立、维护和终止与远程主机之间的通信会话。这是通过传输层协议中的握手和挥手过程来实现的,例如TCP握手过程。
  4. 差错检测与纠正:传输层可以检测并纠正数据传输过程中的错误,确保数据的完整性和正确性。这通常涉及使用校验和和纠错码等技术。

1 - TCP

TCP 是计算机网络中重点,需要熟练掌握 TCP 的可靠传输机制,包含连接建立和断开、流量控制、拥塞控制,常常在选择题和大题中出现。

TCP 特点

  • 面向连接:发送数据前后需要分别通过三次握手和四次挥手进行连接的建立和断开。
  • 可靠交付:保证数据传输的无差错、不丢失、不重复、有序。
  • 面向字节流:以滑动窗口的形式对字节按照顺序进行发送和接收。
  • 全双工:通信双方在一个 TCP 连接中都可以发送和接收数据。

TCP 首部

Source Port (16)
Source Port (16)
Sequence Number (32)
Sequence Number (32)
Options
Options
Data
Data
Destination Port (16)
Destination Port (16)
Acknowledgement Number (32)
Acknowledgement Number (32)
Checksum (16)
Checksum (16)
Urgent (16)
Urgent (16)
Window (16)
Window (16)
Header
Length (4)
Header...
Reserved (6)
Reserved (6)
Flags (6)
Flags (6)
TCP Header
TCP Header
Bit 0
Bit 0
Bit 15
Bit 15
Bit 16
Bit 16
Bit 31
Bit 31
20 Bytes
20 Bytes
Text is not SVG - cannot display
  1. 源端口号(Source Port):16 位字段,指示发送端的端口号。
  2. 目标端口号(Destination Port):16 位字段,指示接收端的端口号。
  3. 序列号(Sequence Number):32 位字段,用于标识 TCP 报文段中第一个数据字节的序列号。这个字段用于实现 TCP 的可靠性机制,如数据的按序传递和重传。
  4. 确认号(Acknowledgment Number):32 位字段,如果设置了 ACK 标志位,该字段包含了期望接收的下一个数据字节的序列号。这个字段用于确认已经成功接收的数据。
  5. 数据偏移(Data Offset):4 位字段,指示 TCP 首部的长度,以 32 位字为单位。这个字段用于指示首部的长度,因为 TCP 首部长度可以变化,根据选项的存在而变化。
  6. 保留(Reserved):6 位字段,保留供未来使用,目前必须设置为 0。
  7. 控制标志位(Flags):TCP 报文段的控制标志,共有 6 个标志位,它们分别是:
    • URG(紧急指针有效位):用于指示紧急数据。
    • ACK(确认位):用于指示确认号字段有效。
    • PSH(推送位):用于指示接收端应立即交付数据给应用层,而不需要等待缓冲区满。
    • RST(复位位):用于强制释放连接,重置连接状态。
    • SYN(同步位):用于建立连接,用于初始化序列号。
    • FIN(终止位):用于关闭连接。
  8. 窗口大小(Window Size):16 位字段,指示发送端的可用接收窗口大小。接收端可以根据这个字段的值来告诉发送端可以发送多少数据而不会导致拥塞。
  9. 校验和(Checksum):16 位字段,用于检测 TCP 首部和数据部分的传输中的错误。
  10. 紧急指针(Urgent Pointer):16 位字段,仅当 URG 标志位设置时才有效。用于指示紧急数据的末尾位置。
  11. 选项(Options):可选字段,用于包含一些额外的控制信息,如最大报文段长度、时间戳等。长度可变,最长可达 40 字节。
  12. 填充(Padding):根据选项字段的长度而变化,用于确保 TCP 首部的总长度是 32 位的倍数。

三次握手

SYN SENT
SYN SENT
SYN  RECEIVED
SYN  RECEIVED
ESTABLISHMENT
ESTABLISHMENT
ESTABLISHMENT
ESTABLISHMENT
SYN = 1
seq: x
SYN = 1...
SYN = ACK = 1
seq: y
ack: x+1
SYN = ACK = 1...
ACK = 1
ack: y+1
ACK = 1...
Text is not SVG - cannot display
  1. 第一次握手(SYN-SENT):
    • 发送方:将 SYN(同步)标志位设置为 1,表示发起连接请求。
    • 序列号(Sequence Number):这是一个 32 位字段,用于标识发送方的 初始序列号ISN,Initial Sequence Number),用于后续的数据传输。ISN 是一个随机数,用于防止连接重放攻击。
    • 确认号(Acknowledgment Number):在第一次握手中,确认号字段被设置为 0,因为此时还没有确认数据的传输。
  2. 第二次握手(SYN-RECEIVED):
    • 接收方:接收到第一次握手的 TCP 报文段后,将 SYN 标志位设置为 1,表示同意建立连接。
    • 序列号(Sequence Number):接收方生成自己的初始序列号(ISN),并将其放入序列号字段。
    • 确认号(Acknowledgment Number):此时确认号字段被设置为发送方的初始序列号加 1,表示接收到了第一次握手中的序列号。
  3. 第三次握手(ESTABLISHED):
    • 发送方:接收到第二次握手的 TCP 报文段后,将 SYN 标志位设置为 0(因为连接已经建立),并将 ACK(确认)标志位设置为 1,表示确认接收到了第二次握手中的序列号。
    • 序列号(Sequence Number):发送方生成一个新的序列号,用于后续的数据传输。
    • 确认号(Acknowledgment Number):此时确认号字段被设置为接收方的初始序列号加 1,表示接收到了第二次握手中的序列号。

四次挥手

FIN-WAIT-1
FIN-WAIT-1
CLOSE-WAIT
CLOSE-WAIT
ESTABLISHMENT
ESTABLISHMENT
FIN=1
seq = u
FIN=1...
ACK = 1
seq = v
ack = u+1
ACK = 1...
ACK = 1
seq = u+1
ack = w+1
ACK = 1...
FIN = ACK = 1
seq = w
ack = u+1
FIN = ACK = 1...
FIN-WAIT-2
FIN-WAIT-2
TIME-WAIT
TIME-WAIT
ESTABLISHMENT
ESTABLISHMENT
LAST-ACK
LAST-ACK
Text is not SVG - cannot display
  1. 客户端发送连接关闭请求
    • 客户端首先决定不再发送数据,并希望关闭连接。
    • 客户端向服务器端发送一个 TCP 报文,其标志位中包含 FIN(Finish)标志,表示客户端已经完成数据的发送任务。
    • 客户端进入 FIN-WAIT-1 状态,等待服务器的确认。
  2. 服务器端确认客户端的关闭请求
    • 服务器端接收到客户端的 FIN 报文,知道客户端不再发送数据。
    • 服务器端向客户端发送一个 ACK(Acknowledgment)报文作为确认,表示它已收到了客户端的关闭请求。
    • 服务器端进入 CLOSE-WAIT 状态,表示服务器端已经完成数据的发送任务,但仍然可以接收来自客户端的数据。
  3. 服务器端关闭连接
    • 服务器端完成了数据的发送任务后,也想要关闭连接。
    • 服务器端向客户端发送一个 FIN 报文,告知客户端它已经完成了数据的发送,并请求关闭连接。
    • 服务器端进入 LAST-ACK 状态,等待客户端的确认。
  4. 客户端确认服务器端的关闭请求
    • 客户端接收到服务器端的 FIN 报文后,确认服务器端的请求。
    • 客户端向服务器端发送一个 ACK 报文作为确认。
    • 此时客户端进入 TIME-WAIT 状态,等待足够的时间,以确保服务器端收到了确认,然后再关闭连接。

滑动窗口机制

0
1
...
74
75
76
77
78
79
80
81
82
...
1660
1671
1672
1673
...
4194304
0
1
...
74
75
76
77
78
79
80
81
82
...
1660
1671
1672
1673
...
4194304
发送窗口
接收窗口
已被确认
已发送
未发送
已接收
未接收
所有的应用层数据
使用 seqno 封装下标进行发送

上图是滑动窗口的简图,滑动窗口代表当前 发送方正在发送 以及 接收方正在接收的 数据窗口,数据窗口是所有数据中的一部分。

每当发送方收到接收方的 ACK 确认后,滑动窗口就会向前滑动。这样,窗口中新位置允许新的数据发送

滑动窗口的大小表示发送方在未收到接收方确认(ACK)的情况下,最多可以发送多少字节的数据。窗口大小由接收方决定,并通过 ACK 报文中的窗口字段告知发送方。

可靠传输机制

TCP 的可靠传输通过多种机制共同实现,下文将对三个关键机制进行介绍。

序列号 和 确认号

序列号(seqno, sequence number) 和 确认号(ackno, acknowledge number) 是 TCP 首部的两个字段,TCP 协议通过 序列号 来记录目前已经发送了哪些数据,通过 确认号 记录哪些数据已经被接收方所接收。

发送方发送序列号 和 接收方返回确认号 的交互可能存在以下几种情况:

  • 如果发送的数据段丢失了,接收方不会发送更新的确认号,这会最终导致发送方超时并重传丢失的数据段。
  • 如果数据段到达了接收方,但是是乱序的,接收方将持续发送最后一个正确序列号的确认,提示发送方其中有数据段需要重新传输。
  • 如果数据段到达了接收方,并且是按顺序的,接收方发送一个新的确认号,提示发送方到目前为止的所有数据都已正确接收。

超时重传

TCP 协议在发送一个 数据段(segment) 时,它会记录目前正在传输的 segment,并为每一个 segment 设置一个定时器。

如果某个 segment 的定时器超时了,就说明发送方在 超时时间阈值 内没有接收到该 segment 的确认,发送方就会触发超时重传(Retransmission Timeout),重新发送超时的 segment。

校验和

TCP 首部包含一个校验和(Checksum)字段,用于检测数据在传输过程中的任何变化。如果接收方检测到校验和错误,该数据段会被丢弃,然后接收方会要求发送方重传该数据段。

TCP 的校验和计算方法和 IP校验和计算方法 一致,不过两者校验的范围和目的有所不同。

其IP校验和只针对IP头部进行校验,主要用于检测数据在传输过程中由于网络故障等原因造成的错误。 而TCP校验和不仅要校验TCP头部,还要校验TCP载荷(即数据部分)。因此,TCP校验和能提供更全面的错误检测。

流量控制

TCP(Transmission Control Protocol)流量控制是一种机制,用于确保在网络中的发送方和接收方之间协调数据传输速率,以防止接收方不堪重负并避免数据包的丢失。TCP 流量控制的主要目标是保证数据的可靠传输,同时有效地利用可用的网络带宽。

TCP 通过 滑动窗口机制 来实现流量控制:发送方根据接收方通告的窗口大小发送数据,而接收方根据自己的处理速度和可用内存来控制窗口大小。

  • 窗口大小(Window Size):TCP 流量控制使用窗口大小来管理数据流的速率。窗口大小表示发送方可以在没有接收方确认的情况下发送的未被确认的数据量。窗口大小由接收方通过 TCP 报文中的通告窗口字段通知发送方。
  • 滑动窗口的调整:窗口大小是动态调整的,它会根据网络条件和接收方的状态而变化。如果接收方的缓冲区快满了,通告窗口大小可能会减小,以减缓发送速率;如果接收方的缓冲区有足够的空间,通告窗口大小可能会增大,以提高发送速率。
  • 零窗口控制:如果接收方的缓冲区已满,它可以将窗口大小设置为零,表示不接受任何数据。发送方会注意到这一点并暂停数据的发送,直到接收方准备好接收数据。
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22
23
23
24
24
25
25
26
26
27
27
28
28
29
29
30
30
Usable
Window
Usable...
TCP
Send Window
TCP...
Sent and Acked
Sent and Acked
Sent and  not acked
Sent and  not acked
Not sent
Recipient ready to recv
Not sent...
Not Sent
Recipient not ready to recv
Not Sent...
* * *
* * *
* * *
* * *
Text is not SVG - cannot display

TCP 的发送窗口可以按照逻辑划分为四个部分:

  1. 已经发送并且被确认的数据(字节流)
  2. 已经发送但还没有被确认
  3. 尚且还没有发送
  4. 暂时不可以发送

其中第 2、3 个部分构成 TCP 的发送窗口,当发送方收到 ackno 在第 2 个部分内的确认报文时,调整滑动窗口的大小后向前移动滑动窗口,并且发送接下来可以发送的数据。

13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22
23
23
24
24
25
25
26
26
27
27
28
28
29
29
30
30
Available
Window
Available...
TCP
Recv Window
TCP...
Received and Accepted
by application
Received and Accepted...
Received but not accepted
Received but not accepted
Not Received
Not Received
Not ready to be received
Not ready to be received
* * *
* * *
* * *
* * *
Text is not SVG - cannot display

TCP 的接收窗口可以按照逻辑划分为四个部分:

  1. 已经被应用层接收的数据
  2. 已经被 TCP 接收,但是还没有被应用层接收的数据
  3. 还没有接收到的数据
  4. 还不可以接收到的数据

拥塞控制

tcp 的拥塞控制指的是 tcp 限制传输数据的速率,进而防止注入过多的数据到网络中,进而造成网络链路过载。

大家需要了解,tcp 不是一个 “自私” 的算法,一段链路上可以同时包含很多 tcp 连接,tcp 的拥塞控制的目的是尽量去实现一个总体的最优,而不是个体的最优。当 tcp 检测到数据传输出现拥塞之时,即一段时间内没有接收到一些确认,它就会降低自己传输数据的速率。

需了解如下的TCP拥塞控制算法:

慢开始

慢开始是 TCP 连接开始时的一个阶段,相较于直接以较高的速率发送数据,慢开始会以一个较低的速率开始,然后逐步试探当前网络传输的能力,以指数的速率增加发送速率。慢开始的流程如下:

  • 初始化:当一个 TCP 连接开始时,拥塞窗口 cwnd 设置为一个很小的值,通常是 1MSS (最大段大小)。
  • 指数增长:对于每个收到的 ACKcwnd 会增加一个 MSS 。这意味着每个 RTT (往返时间) cwnd 都会翻倍,导致了指数增长。
  • 转换阈值:当 cwnd 达到 ssthresh (慢开始阈值)时, TCP 会从慢开始模式转换到拥塞避免模式。
Sender
Receiver
Data
ACK
RTT
每收到一个 ACK,
cwnd += 1
cwnd 在到达 ssthresh 之前指数型增长
0
1
2
3
4
5
2
4
6
8
10
12
14
16
RTT
cwnd
ssthresh

拥塞避免

  • 线性增长:在这个阶段,每收到一个 ACK, cwnd 增加 1/cwnd 的大小。这导致了每个 RTTcwnd 只增加约一个 MSS ,这是一个线性的增长。
  • 拥塞检测:如果发生了超时或者收到三个重复的 ACK (意味着网络中的数据分段丢失),则认为发生了网络拥塞。此时, ssthresh 会被设置为当前 cwnd 的一半,并将 cwnd 重新设置为 1MSS ,然后重新进入慢开始阶段。

快速重传和快速恢复

传统的TCP重传是基于重传计时器的:当计时器到期而没有收到ACK时,TCP会重新发送数据(超时重传)。然而,在有高带宽或低延迟的网络中,等待这个计时器到期可能是低效的。

快速重传 机制是当发送方连续收到三个重复的ACK(表示同一个数据段)时,它会立即重传下一个待确认的数据段,而不是等待重传计时器到期。这三个重复的ACK是网络中丢失一个分段的一个早期指示。

一旦触发了快速重传,TCP进入 快速恢复 模式,按照书上的说法,触发了快速重传后,ssthreshcwnd 都被设定为快速重传前 cwnd 值的一半,然后执行拥塞避免算法。

但是在实际 TCP 的实现中 ssthresh 被设定为当前 cwnd (拥塞窗口)的一半。同时, cwnd 也会被设定为 ssthresh 加上三个 MSS (最大段大小),然后执行如下策略:

  • cwnd 的增加:在快速恢复期间,每当收到一个重复的 ACKcwnd 都会增加一个分段的大小。这是为了用新的数据分段平衡可能在传输路径中出现的丢失。
  • 退出快速恢复:当发送方接收到一个新的、非重复的 ACK ,这表示之前丢失的分段已被成功接收。这时, TCP 会退出快速恢复模式,并将 cwnd 设置为 ssthresh 的值,然后进入拥塞避免阶段。

这里注意一下即可,考试考到的话按照书中方式计算 cwnd

0
2
4
6
8
10
12
14
16
18
20
22
24
4
8
12
16
20
24
28
32
36
40
ssthresh
Congestion
avoidance
RTO
expiration
cwnd(new)
slow
start
slow
start
Congestion
avoidance
ssthresh (new)
0
2
4
6
8
10
12
14
4
8
12
16
20
24
28
32
36
40
ssthresh
Congestion
avoidance
cwnd(new)
Congestion
avoidance
slow
start
ssthresh (new)
TCP slow start and contgestion avoidance
TCP fast retransmit and fast recovery
16
18
20
22
24
Three duplicate
ACKs
Congestion
avoidance
expected ACK
Round Trip Time (RTT)
congestion window (cwnd)
Round Trip Time (RTT)
congestion window (cwnd)
Fast retransmit
and fast recovery

总结一下:

  • cwmd < ssthresh时,使用慢开始算法,swnd以指数增长
  • cwmd >= ssthresh时,使用拥塞避免算法,swnd线性增长
  • 当在 RTO 内没有收到发送的某个分组的确认时
    • 如果启动了快速恢复,则设置cwnd = ssthresh = cwnd / 2,开始使用拥塞控制算法
    • 如果没有启动快速恢复,则设置ssthresh = cwnd / 2, cwnd = 1,开始使用慢开始算法
  • 如果启用了快速重传,并且收到 3 个与先前重复的 ACK(总共收到 4 个相同的 ACK),则不用等待超时器 RTO 结束,可以马上重传该数据包,cwnd 可能会减少(这里不考察)

窗口大小

初始窗口大小?

TCP连接的初始窗口大小可以根据TCP/IP协议栈的实现和操作系统的配置而有所不同。通常情况下,初始窗口大小是根据TCP的初始拥塞窗口(Initial Congestion Window,ICW)来确定的。

RFC 6928建议了一种用于确定TCP连接初始拥塞窗口大小的算法,该算法是根据实验和观察得出的最佳实践。根据这个RFC,初始拥塞窗口大小(ICW)的推荐值为10个MSS (了解即可)。

发送窗口的大小?

发送窗口大小为拥塞窗口和接收窗口中的较小值,swnd = min(cwnd, rwnd),当发送方收到来自接收方的确认报文时,会根据其中的 window 字段来调整 rwnd 大小,也会根据收到的确认信息或者超时去调整 cwnd 的大小。当 cwnd 或者 rwnd 变化时,会调整 swnd 的大小。

接收窗口的大小?

接收方会根据自身处理能力和缓冲区的情况来动态调整窗口大小。如果接收方的应用程序不能及时处理接收到的数据,或者接收方的缓冲区已经满了,它就会减小窗口大小,以通知发送方降低发送速率。

2 - UDP

了解 UDP 的概念和应用,对比与 TCP 的不同,可能在选择题中考察。

UDP 数据报

Source Port (16)
Data
Destination Port (16)
Checksum (16)
Length (16)
Bit 0
Bit 15
Bit 16
Bit 31
8 Bytes
UDP Header

UDP(User Datagram Protocol)首部的长度固定为 8 个字节(64 位),不论 UDP 携带的数据量大小如何,其首部都保持不变。UDP 首部的各个字段如下:

  • 源端口(Source Port):占用 2 个字节(16 位),用于标识发送方应用程序的端口号。
  • 目标端口(Destination Port):占用 2 个字节(16 位),用于标识接收方应用程序的端口号。
  • 长度(Length):占用 2 个字节(16 位),指示 UDP 数据报的总长度,包括首部和数据。因此,最小长度为 8 字节。
  • 校验和(Checksum):占用 2 个字节(16 位),用于检测 UDP 数据报在传输过程中是否受到损坏。

当传输层从 IP 层收到 UDP 数据报时,就根据首部中的目的端口,把 UDP 数据报通过 相应的端口,上交最后的终点一一应用进程,如下图所示:

端口 1
端口 2
端口 3
UDP 分用
IP 层
UDP 数据报到达

若接收方 UDP 发现收到的报文中的目的端口号不正确(即不存在对应于端口号的应用进程),则就丢弃该报文,并由 ICMP 发送“端口不可达”差错报文给发送方。

UDP 校验

UDP 的校验和(checksum)用于检测数据在传输过程中是否发生错误。它覆盖 UDP 头部、数据部分以及部分 IP 头部信息(伪头部),确保数据的完整性。

这种简单的差错检验方法的校错能力并不强,但它的好处是简单、处理速度快。

发送端

UDP 的发送方需要计算 checksum 字段的值,并且填充进 UDP 首部相应字段中。 发送方计算 checksum 包含构造伪首部、组合校验数据、计算 16 位和、按位取反四个步骤。

源 IP 地址
目的 IP 地址
0
17
UDP 长度
伪首部
源端口
目的端口
长度
校验和
首部
数据
4
4
1
1
2
字节
字节
12
2
2
2
2
UDP 数据报
  1. 构造伪头部

为了确保源和目的地址的正确性,UDP 校验和包含一个伪头部(不实际传输,仅用于计算)。伪头部包括:

  • 源 IP 地址(32 位,IPv4)
  • 目的 IP 地址(32 位,IPv4)
  • 协议字段(8 位,UDP 为 17)
  • UDP 长度(16 位,UDP 头部+数据的总字节数)
  • 填充位(8 位,通常为 0,确保伪头部长度为 12 字节)
  1. 组合校验数据

将以下内容按 16 位分组:

  • 伪头部
  • UDP 头部(包括源端口、目的端口、长度、校验和字段,校验和字段初始置 0)
  • 数据部分(若数据长度为奇数字节,末尾补 0 凑成 16 位)
  1. 计算 16 位和
  • 将所有 16 位数逐一相加,记录进位。
  • 如果有进位(和超过 16 位),将进位加到低 16 位(称为 回卷)。
  • 例如:若两个 16 位数相加得 1 0000 0000 0000 0001,则取低 16 位 0000 0000 0000 0001 并加 1,得 0000 0000 0000 0010
  1. 按位取反
  • 对最终的 16 位和按位取反(0 变 1,1 变 0),得到校验和。
  • 将此校验和填入 UDP 头部的校验和字段。
  1. 特殊情况
  • 如果校验和计算结果为全 0,则发送 1111 1111 1111 1111(全 1),以避免与“校验和禁用”(全 0)混淆。
  • UDP 校验和是可选的,若不使用,校验和字段置为全 0。

注意

  1. 检验时,若 UDP 数据报部分的长度不是偶数个字节,则需填入一个全 0 字节进行填充

  2. 若 UDP 检验和检验出 UDP 数据报是错误的,则可以丢弃,也可以交付给上层,但是需要附上错误报告,即告诉上层这是错误的数据报。

  3. 计算 16 位和的过程中,如果有进位,不要忘记 “回卷”。

接收端

接收端通过以下步骤验证数据完整性:

  1. 提取校验数据:接收端同样构造伪头部(使用接收到的 IP 头部信息),并提取伪首部、UDP 首部(包括接收到的校验和)、数据部分。
  2. 计算 16 位和:将所有 16 位数(包括接收到的校验和)相加,记录并回卷进位。如果数据无误,和的结果应为 1111 1111 1111 1111(全 1)。
  3. 验证结果
    • 如果最终和为全 1,说明数据正确,无错误。
    • 如果和不为全 1,说明数据在传输中发生错误,接收端通常丢弃该数据报(UDP 不负责重传)。
  4. 处理特殊情况
    • 如果接收到校验和为全 0,表示发送端禁用了校验和,接收端可直接接受数据(不校验)。
    • 如果校验和为全 1,需按上述步骤验证。

实例

假设我们要发送一个 UDP 数据报,相关信息如下:

  • 源 IP 地址:192.168.1.1(二进制:11000000 10101000 00000001 00000001)
  • 目的 IP 地址:192.168.1.2(二进制:11000000 10101000 00000001 00000010)
  • 源端口:1024(二进制:00000100 00000000)
  • 目的端口:2048(二进制:00001000 00000000)
  • 数据:0x48656C(3 字节,“Hel”)

则得到 16 位组合数据和校验和计算过程如下所示:

192.168.1.1
192.168.1.2
0
17
11
1024
2048
11
全0
数据
数据
数据
0填充
12B
伪首部
8B
UDP 首部
3B 数据
11000000 10101000 →
192.168
00000001 00000001 →
1.1
11000000 10101000 →
192.168
00000001 00000010 →
1.2
00000000 00010001 →
填充 + 协议
00000000 00001011 →
长度 11
00000100 00000000 →
源端口 1024
00001000 00000000 →
目的端口 2048
00000000 00001011 →
长度 11
00000000 00000000 →
校验和 0
01001000 01100101 →
数据 "He"
01101100 00000000 →
数据 "l" + 补0
11000100 11100000 →
16 位和
00111011 00011111 →
校验和

计算得到的校验和为:00111011 00011111(十六进制:0x3B1F)。

当接收端接收到 UDP 数据报是,接收端将所有 16 位数(包括校验和 00111011 00011111)相加:

重复上述加法,最后一步加上校验和:11000100 11100000 + 00111011 00011111 = 11111111 11111111(全 1)

UDP 特点

  • 无连接性:UDP 是一种无连接的协议,这意味着在发送数据之前,发送方和接收方之间不建立连接。每个 UDP 数据报都是独立的,没有先后顺序的要求。
  • 轻量级:UDP 非常轻量级,因为它不涉及连接建立和维护,也不包括复杂的拥塞控制算法。这使得 UDP 非常适用于低延迟和高吞吐量的应用。
  • 无序性:UDP 数据报在传输过程中不保持顺序。这意味着发送方发送的多个 UDP 数据报可能以不同的顺序到达接收方,并且接收方需要自行处理数据的顺序问题。
  • 不可靠性:UDP 不提供可靠性。它不保证数据的传输成功,也不负责重新发送丢失的数据。如果数据在传输过程中丢失或损坏,接收方将不会收到任何通知,并且需要根据应用程序的要求自行处理这些问题。
  • 广播和多播:UDP 支持广播和多播,允许一个 UDP 数据报同时发送到多个接收方。

应用场景

UDP 常用于 一次性传输较少数据 的网络应用,如 DNS、SNMP 等,因为对于这些应用,若采用 TCP,则将为连接创建、维护和拆除带来不小的开销。

UDP 也常用于 对延迟敏感 多媒体应用(如 电子游戏、实时视频会议、流媒体等),显然,可靠数据传输对这些应用来说并不是最重要的, 但 TCP 的拥塞控制会导致数据出现较大的延迟,这是它们不可容忍的。

UDP 不保证可靠交付,但这并不意味着应用对数据的要求是不可靠的,所有维护可靠性的工作可由用户在应用层来完成。应用开发者可根据应用的需求来灵活设计自己的可靠性机制。

比如 HTTP3 中使用的 QUIC 就是在 UDP 的基础上实现的一种可靠传输协议。