TCP序列号如何在双向通信/滑动窗口中工作?

网络工程 tcp 网络 传输协议
2022-02-23 00:21:49

我试图了解 TCP 的工作原理(当然不是详细的)。我在网上浏览易于理解的流程图时出现了一个问题,但找不到直接的答案。

让我们假设我们有一个很好的流程,其中所有内容都是同步的(忽略带有 FIN 和交叉数据包的结尾部分): 在此处输入图像描述

看这个示意图可以理解,B 只能将数据作为对某事的响应发送给 A,但据我所知,TCP 是一种双向协议,因此每个实体都可以随时发送它。

  1. 我想知道如果 A 和 B 同时发送数据包会发生什么。基本上有交叉数据包,序列号和确认将如何表现。最初,我认为 B -> A 连接的镜像中也发生了同样的事情(每个方向都有一组 seq 数字),但这真的没有意义。在示例中,“hello”是为响应“foobar”而发送的,这会与 B -> A 连接的序列号混淆。

  2. 同方向的另一个问题,我读到 TCP 是一个 SWP(滑动窗口协议),我想知道在这种情况下 ACK 是如何形成的。TCP 响应的字节数基本上是 Seq 数,我真的无法想象在窗口内会发生这种情况(您可以按任何顺序接收)。是否为接收方和发送方使用两组序列号和两个窗口?

  3. 在以下情况下会发生什么:

在此处输入图像描述

任何规范参考或其他有用的资源都非常受欢迎。

2个回答

相当简单:每个方向都有自己独立的序列号和滑动窗口。因此,两端是单向发送数据(一端只是用其他空段进行确认)还是双向发送都无关紧要。

TCP 只作用于它接收到的数据包,它不知道在线上的数据包。

如果双方同时发送数据,从 TCP 的角度来看,它会先发送数据,然后接收数据,然后接收到一个包含 ACK 的数据包

A方视角的例子:

A -> B: SEQ=1000 SYN=1000        (SYN is a random value in practice)
A <- B: SEQ=0    ACK=1001 SYN=0  (SYN is a random value in practice)
A -> B: SEQ=1001 ACK=1           (When the packet contains only an ACK, 
                                  don't increase the sequence number for
                                  the next packet)
(A knows it sending sequence number is 1001, and the receiving sequence number is 1)
// Example: Only A sends something
A -> B: SEQ=1001 ACK=1 "hello "
A <- B: SEQ=1    ACK=1007 (We acknowledge that 6 bytes have been received)

// Example: Only A sends multiple things quickly
A -> B: SEQ=1007 ACK=1 "World"
A -> B: SEQ=1013 ACK=1 "!"
A <- B: SEQ=1    ACK=1013
A <- B: SEQ=1    ACK=1014

// Example: Both sides send data at the same time
A -> B: SEQ=1014 ACK=1 "Ping!"
A <- B: SEQ=1    ACK=1014 "Hello"
A -> B: SEQ=1019 ACK=6
A <- B: SEQ=6    ACK=1019

// Example: Both sides send data, but B's data packet takes a
// slow route though the internet
A -> B: SEQ=1019 ACK=6 "1"
# B sends the data, the packet is delayed
# B receives the data from A and sends an (SEQ=7, ACK=1020)
A <- B: SEQ=10   ACK=1020
# A sees that it missed some data, but doesn't respond back. It is
# B's responsibility to detect missing ack's and resend data if needed.
A <- B: SEQ=6    ACK=1019 "Data"
# Out of order packet detected (SEQ/ACK values decremented)
# We already know the other side has acknowledges up to 1020, so we remember that value
A -> B: SEQ=1020 ACK=10

// Complex example: Multiple packet are lost/reordered
// (packets from a real world traffic capture I did in my own network)
// The remote side is supposed to say "Hello World!"
A -> B: SEQ=1020 ACK=10 "/MOTD"
A <- B: SEQ=10   ACK=1025
A <- B: SEQ=16   ACK=1025 "World!"
# Note how the sequence ID is suddenly bigger
A -> B: SEQ=1025 ACK=10
# We have received everything correctly up to 10, so only send 10 back
A <- B: SEQ=10   ACK=1025 "Hello "
A -> B: SEQ=1025 ACK=22
# Note how the ack number shoots up by 12, even though we only received 6 bytes of data
A <- B: SEQ=16   ACK=1025 "World!"
A -> B: SEQ=1025 ACK=22
# We receive the same data again, we already know about this, and we already processed it. It must alrady be send before the other side received our ACK

同方向的另一个问题,我读到 TCP 是一个 SWP(滑动窗口协议),我想知道在这种情况下 ACK 是如何形成的。TCP 响应的字节数基本上是 Seq 数,我真的无法想象在窗口内会发生这种情况(您可以按任何顺序接收)。是否为接收方和发送方使用两组序列号和两个窗口?

TCP 最初是为较慢的网络设计的。序列号是一个 32 位的数字,每传输 4GB 的数据就会翻转一次。当我们在拨号时这很好,因为我们只有 KB 范围内的互联网速度,但是这个系统在现代互联网速度下失败,它可以在几秒钟内翻转。这些天我们为数据包添加了“时间戳”,它增加得更慢,它与其他字段结合使用来处理乱序、重复数据包和翻转序列号