TCP是如何实现可靠连接的?

24次阅读

共计 1760 个字符,预计需要花费 5 分钟才能阅读完成。

***TCP 是如何实现可靠连接的?***
TCP 是面向连接的协议,它与 UDP 的不同之处主要有两点:
1、TCP 是面向连接的,而 UDP 是不面向连接的;
2、TCP 的信息传输是可靠的,而 UDP 的信息传输是不可靠的。
那么 TCP 是如何实现可靠连接的呢?
TCP 协议主要通过检验和、序列号、确认应答(ACK)、重发控制、连接管理、窗口控制等实现可靠性连接。

** 一、确认应答:ACK(Positive Acknowled-gement)意指已经接收。**

假设没有丢包,那么发送端每次发送数据后都会受到接收端的确认应答(ACK),发送端只有受到接收端的确认应答(ACK)后,才会继续发送数据。

假设发送过程中产生了丢包,那么在特定时间内发送端将无法受到接收端的确认应答(ACK),之后发送端会重新发送之前的数据,直到在发送数据后的特定时间内受到接收端的确认应答(ACK)。

** 请思考:那么如果出现以下情况怎么办?**
根据上面说的规则,发送端只有在特定时间内接收到的 ACK 才会停止重新发送之前的数据,那么如果发送端发送数据后,因为网络延迟等原因,接收端发送的 ACK 出现了延迟,导致发送端在特定时间外接收到接收端的 ACK,那对接收端来说就是一个“灾难”——它在不断地接收发送端发来的重复数据。

** 二、序列号 **
看了上述思考题后,首先我们会想到这种情况是完全有可能的,因为网络的不稳定很有可能导致这种情况,但是 TCP 要保证无论是在何种情况下都要有高性能的传输能力,那么该如何做呢?
为了避免上述情况,保证 TCP 高性能的传输能力的特性,协议中给发送端的每段数据都规定了一个序列号。

如下图所示,为了方便起见,我们将数据按照 1000 为一个单位,数据的初始序列号为数据量(实际中是以数据的散列值为准),每当发送端发送数据时,会将序列号放入 TCP 包的首部中,然后接收端接收到数据后会解析 TCP 包的首部,在序列号的基础上 + 1 生成新的序列号,通过 ACK 发回给发送端,那么即使当发送端在特定时间外接收到之前接收端返回的 ACK,发送端会根据序列号判断是否要继续重新发送之前的数据。自此,通过序列号我们解决了因网络延迟的问题不断重新发送相同数据的情况。

** 请思考:通过上文,我们了解到 TCP 发送数据后会有一个特定的等待时间,如果这个等待时间过长,那么势必会导致数据传输性能减弱,如果过短,那么发送端将会发送多次相同数据,同样导致数据传输性能减弱,那么如何做到合理的规定这个特定的等待时间呢?**

** 三、重发控制 **
首先我们将那个等待的特定时间定义为重发超时——是指重发数据之前,等待 ACK 到来的那个特定时间。
TCP 要求不论在何种网络环境下都要提供高性能通信,并且无论网络拥堵情况发生何种变化,都必须保持这种特性。为此,它在发包时都会计算往返时间及其偏差。
计算完往返时间及其偏差后,将往返时间加上偏差就能得出重发超时。
数据被重发之后若还是收不到确认应答,则进行再次发生。此时,等待确认应答的时间将会以 2 倍、4 倍的指数函数增长。此外,数据不会被无限、反复的重发。达到一定重发次数之后,如果仍没有任何确认应答返回,就会判断为网络或对端主机发生异常,强制关闭连接。并且通知应用通信异常强行终止。

** 请思考:得到重发超时后,按理我们已经基本已经完成了基本的可靠性传输,能够保证丢包后重新发送并且不会出错,那么为什么 TCP 还要规定其他的东西呢?目前我们完成的协议是否有弊端?该如何解决?**

** 四、窗口控制 **
在了解什么是窗口控制前,我们需要知道的是之前我们完成的方案是存在弊端的,那就是实际传输效率很低。那是因为每次我们要发一个包都得等一个 ACK 甚至是重发超时 +ACK 的时间,如果发送的数据很多,那么势必会影响到传输速度,而这显然违背了 TCP 高性能传输的特性。
为了解决这个弊端,TCP 提出了一个很好的解决方案——窗口控制。

如图下图所示,ACK 不再是以每个分段,而是以更大的单位进行确认时,转发时间将会被大幅度的缩短。也就是说,发送端主机,在发送了一个段以后不必要一直等待确认应答,而是继续发送。

自此,我们基本实现了高性能的可靠性传输,而 TCP 在此之外还规定了其他的内容,如流控制,用来处理缓冲区满的情况等等,这些内容进一步提高了传输性能。
最后,建议初学者可以去看《图解 TCP/IP》。

正文完
 0