学习笔记:TCP 传输控制协议(一)
《TCP/IP 详解》是关于网络传输中最经典的一本书,篇幅和文字内容都非常详实,不是短时间能看完的,最近正好也在啃,很多地方茅塞顿开,这里会更新一些自己的理解与认识,希望能有所参考。
工作在传输层的 TCP 协议,到底为了解决什么样的问题?我们知道,通信媒介可能会丢失或是改变被传递的内容(如同快递可能丢失或是被损坏),我们当然希望发送一段数据后接收方看到的和我们发送的一致。那如果传输过程中出错该怎么解决呢,有两种比较常用的方法,一种是“差错矫正码”,通过添加一些冗余的比特使得即使某些比特丢失,依然能恢复;另一种就是简单的“尝试重新发送”,这被称为自动重复请求(Automatic Repeat Request,ARQ),TCP 就是使用的后者。
再进一步思考,怎么确保重发信息直到它被正确地接收呢,对于发送方来说有这两个方面需要明确:1)接收方是否已收到分组;2)接收到的该分组是否与发送的一致。对此,我们使用的方法是“确认(Acknowledgment,ACK)”,即发送方发送一段数据后停下,等待一个 ACK;接收方收到这个数据后返回一个 ACK;发送方收到这个 ACK 的时候就继续发送。
但这个模型仔细思考一下还有些细节上的问题:例如发送方对于 ACK 应该等待多久?ACK 丢失了怎么办?接收方收到了信息但里面有错误时该怎么解决?
第一个问题还挺复杂的,网络环境千变万化,这个等待时间长了影响传输效率,短了又可能收不到 ACK 导致重复发送(还是影响传输效率),将在以后讨论(书里的第 14 章整整一节)。第二个问题,如果接收方发的 ACK 丢失了,那对于发送方来说还是没有收到,它只能重新再发送(此时接收方可能会收到多个重复内容,解决方法后文讲继续讨论);至于第三个问题,可以使用 CRC 校验和的方式进行校验(如果某位传输错误会导致这个值不一样),当接收方收到这样的一个错误分组时,不会发送 ACK。
到这里,我们发现对于接收方而言可能会收到多个重复的分组,这个问题使用了序列号(sequence number)来解决:发送端的每个分组都有一个新的序列号并一直携带,接收方可以使用这个序列号来做判断,如果已经收到了则丢弃它。
目前为止,我们针对网络传输设计的这个模型已经可以保证可靠的传输信息了。以上关于差错的讨论都是建立在假设网络环境不好的情况下,那如果在一个理想环境下这个模型会有什么问题呢?由于每发送一个分组都要等待一个 ACK 才能继续发,这个传输效率是不高的(如果是要在北京和美国之间传输,每等待一个 ACK 都意味着增加了一次传输距离,极大地增加了信息传递的时间)。所以这种模型也被称为“传输和等待”,那为了增加传输效率,让网络处于一个“繁忙”的状态,我们可以考虑同时发送多个分组,只是这会让事情更复杂。
现在发送方要决定同时传输多少个分组到网络中,此外在等待 ACK 时,需要保存还没有 ACK 的分组的一个拷贝以防止重传;接收方要考虑的事情更多:需要区分哪些分组已经收到哪些还没有;比预想中要收到的分组更前的分组来了该怎么处理(乱序);另外如果发送方一次发送了很多分组但接收方(或是中间负责传输的路由器)来不及处理这些信息该怎么办......TCP 为了解决这些问题,使用了一种“滑动窗口”的思路,这也是后续会聊到的内容。
PS:
在工作和生活中去了解网络协议,有时候会图快而去看一些更简单更薄的书籍文章,这类文章会直接了当的告诉你 TCP 这样的一个“滑动窗口”协议是怎么实现的,这样看起来也许会学的快一点,但实际上未必能完全理解这背后的设计,在我看来反而是直接啃这本书来的更快。很多困难我们是逃避不了的,终究还是要去直面他们。而这本书在讲 TCP 这样复杂的网络协议时,并没有一上来就讲重传怎么设计滑动窗口怎么设计,而是从一个问题出发,在解决这个问题的过程中还遇到了哪些问题,这些新的问题又该怎么解决,逐渐展开,这个思路让我很佩服,因为知道这些才是知道 TCP 为什么设计成现在这个样子的原因。工作生活中又何尝不是如此,以为解决了一个问题,但往往发现又有新的问题要去解决,不过也正是因为如此,我们的科技文明才不断向前发展吧。
版权声明: 本文为 InfoQ 作者【姬翔】的原创文章。
原文链接:【http://xie.infoq.cn/article/2b9effdd64e5541de4f68f915】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论