TCP 怎么工作
寄出的信要是有一页在路上丢了,或者后面那页先到了,会怎样?互联网上的数据包也一样:有的会在路上丢失,有的顺序会颠倒。尽管如此,文字还是能完好地送到,这要归功于 TCP。
一样不漏,准确无误
前面看到,数据会变成叫作数据包的小块,沿着不同的路分头过去。可这些路并不完美:有一块可能在半路丢了,后面的一块也可能先到。
即便如此,接收方也必须一块不缺、按顺序收到。负责这件事的约定,就是 TCP。
点两张卡片,打开 TCP 遵守的两个承诺:一块都不丢,并且按发送的顺序送到。
目标很明确:一样不漏,按顺序。说起来容易,可路并不完美,真要做到并不简单。
TCP 靠三个习惯来做到:告诉对方“收到了”、没收到回音就重发、看编号排好顺序。
顺带一提,TCP 在发送数据之前,会先和对方简短地互相打三次招呼,把连接建立起来。
告诉对方“收到了”
第一个习惯是确认。每到一块,接收方就简短地回一句“收到了”,这个回复叫作确认应答,也就是 ACK。
这就像收到快递后点一下“确认收货”。发送方只有收到 ACK,才知道那一块平安到了;没有 ACK,就还不知道。
把到达的数据包一个个点一下,接收方就会回一个确认应答(ACK)。四个都确认过,发送方就知道全部送到了。
每一块都有 ACK 来回,发送方就知道哪些到了。多了一句来回,看起来可能慢了一点。
可正是这一句话,让丢失的那块能被准确找出来。那么,没收到 ACK 的那块该怎么办?答案很简单:再发一次。
没回音就重发
第二个习惯是重传。发送方等了约定的时间,如果某一块的 ACK 还是没来,就认定它在路上丢了,把同样的一块再发一次。
接收方收到重发的那块,这次就回 ACK。像这样把丢失的块补上,最后就一块也不缺了。
点那两个没收到确认应答(ACK)的空位,把那两块重新发送。重发的块一到,空位就补上了。
有了重传,再也没有丢失的块了,所有的块都到了接收方手里。
可还剩一件事:这些块是分头过来的,到达的先后乱成一团,5 号可能比 2 号先到。这个顺序要怎么理顺?
看编号排好顺序
第三个习惯是排序。TCP 给每一块都编上号再发,1 号、2 号、3 号这样。
到达的顺序乱了也没关系,因为接收方会看编号,从小到大依次排好。就算 5 号先到,也会把 2 号的位置空着等它;按编号全部填满后,原来的文字就原样恢复了。
真实的 TCP 不是按块编号,而是按数据的第几个字节来编号,不过道理是一样的。
把乱序到达的块按编号顺序(1、2、3、4)点一遍,就能排好队。点错了,它会提示你点下一个编号;全部排好,原来的文字就回来了。
按编号排好队,乱掉的块就严丝合缝地拼回了原来的文字。丢的重新收到补上,顺序靠编号理顺。
在接收的人看来,好像数据包从来没丢过、也没乱过。这些麻烦事,全是 TCP 在背后默默做完的。
小结
一句话概括:数据包可能丢失,也可能顺序颠倒。TCP 收到就回确认应答(ACK),没回音就重发(重传),再靠编号排好顺序。
所以接收方总能一样不漏、按顺序地收到。可靠胜过速度,这就是 TCP 的承诺。
每点一次按钮,就会多出现一个要点。(丢失/乱序 → 收到回 ACK → 没回音就重传 → 按编号排序)四个都出现,回顾就完成了。
为了安全,TCP 要确认、要重发、要排队,相应地就得多等一会儿。
可有时候,这份等待是种浪费:像语音通话或游戏,宁可丢一点,也要快。下一课,就来讲省掉确认、直接快速发送的方式。