关于《计算机网络:自顶向下方法》一书中 TCP 协议的问题

2022-02-25 16:06:23 +08:00
 rattlecattle
最近在恶补计算机网络的知识,看到了 TCP 协议部分,在第七版 164 页,阐述 TCP 是回退 N 步( GBN )还是选择重传(SR)有这样的论述:

“TCP 看起来更像是 GBN 风格的协议,但是 TCP 和 GBN 有着显著的区别。许多 TCP 实现会将正确接收但失序上网报文段缓存起来。
另外考虑一下,当发送方发送一组报文段 1,2 ,...,N ,并且所有报文段都按序无差错地到达接收方时会发生的情况。
进一步假设对分组 n<N 的确认报文丢失,但是其余 N-1 个确认报文分别在超时以前到达发送端,这时又会发生的情况。在该例中,Go-Back-N 不仅会重传分组 n ,还会重传所有后继的分组 n+1,n+2,....,N 。
在另一方面,TCP 却至多重传一个报文段,即报文段 n 。此外,如果对报文段 n+1 的确认报文在报文段 n 超时之前达到,TCP 甚至不会重传报文段 n.”

很疑惑,GBN 不是累计确认吗? 如果除了 n 其余的 ACK 传回发送方,那么发送方收到了比 n 更高的比如 N > n 的 ACK ,不就确认了这个 N 之前的分组都已经被交付了吗?为什么还会重传 n, n + 1 ,n + 2 ,......,N ?
2398 次点击
所在节点    程序员
6 条回复
1423
2022-02-26 11:02:17 +08:00
sack
ziseyinzi
2022-02-26 11:06:50 +08:00
GBN 接收方没收到 n ,就不会传送 n 及之后包的 ACK ,即使它收到了 n+1 到 N 的包,也只会发送 ACK(n-1)
ruimz
2022-02-26 13:04:14 +08:00
感觉 OP 的理解是对的,对此我想到的可能解释是此处的 GBN 没有启用累计确认
jedihy
2022-02-27 03:45:41 +08:00
这段文字的第一句话就概括了区别,TCP 缓存失序报文段,GBN 不会。所以 TCP 看到重复的 ACK(n),只会重传 n 。接受方收到重传的 n 之后就会发送 ACK(N+1),到此所有报文得到确认。

GBN 重传 n...N ,就是因为它的接受缓存里面没有这些报文,乱序报文都会被丢弃。

说实话,这些书和真正的实现有一些脱轨了,特别是 loss recovery ,RACK 完全改变了 loss recovery 。建议看看 RFC6675 (SACK), RFC6582 (NewReno style loss recovery) 以及 RFC 8985 (RACK)。这三种 loss recovery 是真正主流操作系统在用的 ( Windows 和 Linux )。RFC6582 是在 SACK 没有启用的时候的 loss recovery 。
documentzhangx66
2022-02-27 09:05:40 +08:00
分析历史协议的制定,要考虑当时的主流设备与经济情况。

现在内存便宜,各种网络设备,以及网卡,都能以很便宜的成本,缓存大容量的数据。

但以前不是这个情况,那时候内存死贵,因此大家才愿意牺牲时间,来换取更低成本。因此,等待与重传剩余所有数据,在那个时期,比缓存且仅重传失效数据,在经济价值上要好的多。

这个话题就像千年虫问题一样。其实直接用动态长度的时间变量,能够一次性彻底解决千年虫问题,但经济成本太高了,因为变长的变量,在存储与运算代价,要高于定长变量好几倍,这个问题在很多低成本的小型硬件上影响更大。所以,业界解决千年虫的方案,只是把 32 位变量换成 64 位变量了,虽然能用很长的时间,并且在经济上很划算,但却是治标不治本的方案。
learningman
2022-02-27 18:46:51 +08:00
@documentzhangx66 换成 64 位,能治标的时间有点长。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/836415

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX