可靠传输之TCP协议

Posted the_scent_of_th_soul

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可靠传输之TCP协议相关的知识,希望对你有一定的参考价值。

首先,我们来看一下TCP报文段结构,梳理一下关键字含义:


传输层最常用的两种协议:UDP和TCP。它们最基本的责任是将两个端系统间IP的交付服务扩展为运行在端系统上的两个进程之间的交付服务。在这里我只对提供可靠传输的TCP做介绍。

在讨论图中的TCP报文段之前,我先介绍一下TCP提供的服务:

(1) TCP提供可靠数据传输。通过使用流量控制、序号、确认和定时器,TCP确保正确地、按序地将数据从发送进程交付给接收进程。这样,TCP就将两个端系统间的不可靠IP服务转换成了一种进程间的可靠数据传输服务。
(2)TCP提供拥塞控制,防止过多数据注入到网络中,使网络中的路由器或链路不致过载。

多路分解:当报文段到达主机时,运输层检查报文段中的目的端口号,并将其定位到相应的套接字。然后报文段中的数据通过套接字进入其所连接的进程。

多路复用:在源主机中,从不同的套接字接收数据块,并为每个数据块封上头部信息生成报文段,然后将报文段传递到网络层。

TCP是面向连接运输协议,即在一个应用进程可以开始向另一个进程发送数据之前,这两个进程之间必须建立一条可靠的连接。TCP用一个四元组(源IP地址、源端口号、目的IP地址、目的端口号)标识一个连接。

下面我们来研究一下TCP报文段结构,以帮助理解后面要介绍的内容:

目的端口号(16比特):标识目的主机的一个socket。
源端口号(16比特):标识源主机的一个socket。
序号(32比特):TCP隐式地对TCP报文段 数据部分 的每一个字节编号。TCP报文段首部的序号值是其数据部分第一个字节的编号。
确认号(32比特):接收主机的确认号是期望从发送主机接收的下一个字节的编号。
首部长度(4比特):表示报文段的首部长度,以32比特的字为单位,例如首部长度最大值为154比特)则首部为60字节。
接收窗口(rwnd):一个变量,接收方的报文段中包含该变量值 用于告知发送方自己还有多少可用的缓存空间。

TCP在IP不可靠的尽力而为服务之上创建了一种可靠数据传输服务。TCP的可靠传输确保一个进程从其缓存中读出的数据流是无损坏、无间隔、非冗余和按序的数据流;即该字节流与连接的另一端系统发送出的字节流是完全相同。

我们以解释概念的形式 来讨论TCP解决数据传输中一些常见问题的方式:

注意,我们现在假设主机A用于发送数据,主机B用于接收数据。

定时器

坚持定时器:

假设主机B的接收缓冲区已经存满,使得rwnd为0。在将rwnd=0告诉主机A以后,假设主机B没有任何数据要发送给主机A。或者当主机B更新了rwnd后,有报文段发给主机A,但是这个报文段丢失了。这样,主机A就不可能知道主机B的接收缓冲区已经有新空间了,即主机A被阻塞而不能再发任何数据。为了解决这两个个问题,当主机A收到的报文段中rwnd(也叫接收窗口也叫通告窗口)为0时,就设置它的坚持定时器。如果该定时器时间到,主机A还没有收到任何报文段提示rwnd已经不等于0了的话,主机A就发送包含一个字节数据的窗口探查(就是上次发送数据的下一个字节报文段)。如过主机B的rwnd还是为0就返回一个rwnd为0的ACK,但是这个ACK并没有确认刚刚收到的一个字节数据,而是确认的这个字节以前的所有数据。所以这个字节还是被持续重传。使用坚持定时器的特点就是,TCP从不放弃发送 窗口探查。这些探查每隔60秒发送一次,这个过程持续到 或者接收窗口不为0或者应用进程使用的连接被终止。

流量控制与拥塞控制

流量控制:

一条TCP连接每一侧主机都为该连接设置了接收缓存。当该TCP连接收到正确、按序的字节后,它就将数据放入接收缓存。相关联的应用进程会从该缓存中读取数据,但不必是数据一到达就立即读取。如果应用程序读取数据相对缓慢,而发送方发送得太多太快,发送的数据就会很容易地使该连接的接收缓存溢出。
为了解决这个问题,TCP为它的应用程序提供了流量控制服务以消除发送方使接收方缓存溢出的可能性。TCP通过让发送方维护一个称为接收窗口的变量(就是上面TCP报文段的接收窗口)来提供流量控制。通俗地说,接收窗口用于给发送方一个指示:该接收方还有多少可用缓存空间。具体实现就是在接收方在给发送方发送一个报文段(确认报文段、主动发送的数据)时,报文段头部信息的接收窗口 用于通知 该连接中接收方 剩余缓存区的大小。

拥塞控制:

很多人容易把流量控制和拥塞控制搞混,其实它们是针对完全不同的原因采取的措施。

MSS:TCP可从发送缓存中取出并放入报文段的数据量受限于最大报文段长度。MSS一般根据MTU确定。
路径MTU:是指能从源到目的地的所有链路上发送的最大链路层帧。
注意, MSS是指在报文段里应用层数据的最大长度而不是指包括TCP首部的TCP报文段的最大长度。

在实践中,分组丢失一般是当网络变得拥塞时由于路由器缓存溢出引起的。分组重传因此作为网络拥塞的征兆来对待。但是却无法处理导致网络拥塞的原因,因为有太多的源想以过高的速率发送数据。为了处理网络拥塞原因,需要一些机制以在面临网络拥塞时遏制发送方。
拥塞网络的代价:
1.当分组的到达速率接近链容量时,分组经历巨大的排队时延。
2.发送方在遇到大时延时所进行的不必要重传会引起路由器利用其链路宽带来转发不必要的分组副本。
3.当一个分组沿一条路径被丢弃时,每个上游路由器用于转发该分组到丢失该分组而使用的传输容量最终被浪费掉了。

快速重传:

超时触发重传存在的问题之一是超时周期可能相对较长。当一个报文段丢失时,这种长超时周期迫使发送方延迟重传丢失的分组。因而增加了端到端时延。
解决办法:发送方可在超时事件发生之前通过注意冗余ACK来较好地检测到丢包情况。一旦TCP发送方收到3个冗余ACK,TCP就执行快速重传,即在该报文段的定时器过期之前重传丢失的报文段。

那我们现在来看一下,为什么接收方要发送冗余ACK:当TCP接收方收到一个序号大于下一个所期望的、按序的报文段,它检测到了数据流中的一个间隔,这就是说有报文段丢失。这个间隔可能是由于在网络中报文段丢失或重新排序造成的。因为TCP不能向发送方发回一个显示的否定确认(报文头部信息没有,也没有这个变量)。所以它只对已经接收到的最后一个按序字节进行重复确认,即产生冗余ACK。

慢启动:

拥塞窗口:拥塞窗口表示为cwnd,它对一个TCP发送方能向网络中发送流量的速率进行了限制。特别是,在一个发送方未被确认的窗口的数据量不会超过cwnd(拥塞窗口)和rwnd(接收窗口)中的最小值。(拥塞窗口和接收窗口是在TCP建立时给连接分配的变量)

当一条TCP连接开始时,并不知道网络中能接收的数据大小是多少。所以需要向网络中一点一点发数据探测。cwnd的值通常设置为一个MSS,如果MSS=500字节且RTT=200ms,则得到的初始发送速率大约只有20kbps。由于对TCP发送方而言,可用宽带可能比MSS/RTT大得多,TCP发送方希望迅速找到可用宽带的数量。因此,在慢启动的状态,cwnd的值以一个MSS开始并且每当传输的报文段首次被确认就增加一个MSS,并发送出两个最大长度的报文段。这两个报文段被确认,则发送方对每个确认报文段拥塞窗口增加一个MSS,使得拥塞窗口变为4个MSS,并一直这样下去。这一过程每过一个RTT,发送速率就翻番。因此,TCP发送速率起始慢,但在启动阶段以指数增长。

那么,什么时候结束这种指数增长呢?
(1)如果存在一个由超时指示的丢包事件(即拥塞),TCP发送方将cwnd设置为1并重新开始慢启动过程。并且将慢启动阀门置为拥塞窗口的一半。
(2)慢启动阀门儿有个初始值,当cwnd等于慢启动阀门儿时,结束慢启动并且TCP转移到拥塞避免模式。慢启动阀门儿就是网络最优值。
(3)如果检测到三个冗余的ACK,这时TCP执行快速重传,并进入快恢复状态。

拥塞避免:

当进入拥塞避免状态时,在每个RTT只将cwnd的值增加一个MSS(线性增长)。一种通用的方法是,例如,我在一个RTT内发送10个报文段。则我每收到一个报文段的ACK,就把我的cwnd增加(1/10)个MSS,当我10个报文段的ACK都收到时也就增加了一个MSS。

快速恢复:

相比于超时指示的丢包,一个由三个冗余ACK标识的丢包事件 反应应当不那么剧烈。
当进入快速恢复状态时,TCP发送方不将cwnd设置为1,而是设置为cwnd/2 + 3。
然后就如拥塞避免状态。如果出现超时事件,快速恢复在执行如同慢启动相同的动作。

以上是关于可靠传输之TCP协议的主要内容,如果未能解决你的问题,请参考以下文章

网络协议系列八 - 传输层-TCP之可靠传输

Tcp协议保证可靠传输机制

Tcp协议保证可靠传输机制

TCP协议保证数据传输可靠性的方式

计算机网络 之 运输层 考前复习详细总结

传输层