序列号和确认号对 3-Way Handshake 的处理方式不同吗?

网络工程 tcp 协议论 传输协议 第 4 层
2022-02-28 01:44:21

1- 正如分配给PAR中每条消息的消息 ID 一样,“序列号”是一种在字节流传输中提供可靠性的方法。所以序列号被分配给每一个字节

2-但并非所有字节都被确认,因为那太慢了。所以(根据Kozierok 的书) seq# 和 ack# 计划分别只是发送段的第一个字节的编号和接收段的最后一个字节的编号。(忽略此处的所有细微差别,例如累积/选择性确认等,因为它们与此处的问题无关)。

3-通过前三个数据包的交换,每一方的ISN都被宣布给对方并得到确认(谢谢Eddie)。但是,在第三次数据包交换中,当客户端确认接收到服务器的 ISN 时,seq# 和 ack# 都是 1。

4-这是我的两个问题:

问题 1:ISN(如 seq#)是一个 32 位的数字,即 4 个字节。那么为什么服务器返回的 ack# 不是 3(从 0 开始计数)而不是 1 在交换的第二个数据包中?同样,为什么第三个数据包中的 seq# 和 ack#, 3 而不是 1 都没有交换?这是设计协议的人强迫的例外*还是有其他原因?

现在,如果答案是这些初始增量被异常计为仅 1 个字节,那么它给我们带来了第二个问题:

问题 2:为什么我们在 seq# 和 ack# 增量中进行 ISN 交换?有人可能会说,除了更改 ack# 之外,我们没有其他方式来宣布确认,但 IMO 并非如此。服务器和客户端都可以只检查 SYN 和 ACK 标志来实现一切。

那么我错在哪里?如果有什么我理解错了,请告诉我。先感谢您。


* 在我检查过这是一个“异常”的任何地方都没有明确说明,但我发现这篇文章说:“ SYN、FIN 或 ZeroWindow 段算作 SEQs/ACKs 的 1 个字节。 ”。所以我个人对这条线的解释是我们正在谈论一个“例外”。

1个回答

所以(根据 Kozierok 的书) seq# 和 ack# 计划分别只是发送段的第一个字节的编号和接收的段的最后一个字节的编号。

要么你误解了这本书的内容,要么这本书是错误的。确认号不是发送段的最后一个编号,它是下一个预期段的序列号。确认号与 ACK 标志组合时,告诉对方确认确认号之前的所有数据,但数字本身代表下一个预期的序列号。

您应该阅读RFC 793,传输控制协议,它是 TCP 的定义。这在 RFC 中有明确的解释:

2.6. 可靠的通讯

在 TCP 连接上发送的数据流在目的地可靠且有序地传递。

通过使用序列号和确认使传输变得可靠。从概念上讲,每个八位字节的数据都分配有一个序列号。段中数据的第一个八位字节的序列号与该段一起传输,称为段序列号。段还携带一个确认号,它是反向传输的下一个预期数据八位组的序列号。当 TCP 传输包含数据的段时,它会将副本放入重传队列并启动计时器;当收到对该数据的确认时,将从队列中删除该段。如果在定时器用完之前没有收到确认,则重传该段。

TCP 的确认并不能保证数据已经交付给最终用户,而只能保证接收方 TCP 承担了这样做的责任。

为了管理 TCP 之间的数据流,采用了流控制机制。接收 TCP 向发送 TCP 报告一个“窗口”。此窗口指定接收 TCP 当前准备接收的八位字节数,从确认号开始。