TCP协议可靠传输的实现

TCP协议是一种运输层协议,该层通信的端点是主机中的进程,利用套接字实现两个主机特定进程的通信。运输层采用面向连接的TCP协议时,便可在不可靠的网络上实现一条全双工的可靠信道。TCP协议的主要特点有:面向连接,点对点信道,可靠交付,全双工通信,面向字节流。为实现可靠传输并确保信道的可用性,TCP协议考虑了四个方面的内容:数据传输连接的建立与释放,滑动窗口协议(连续ARQ的实现),流量控制,拥塞避免。

1.TCP报文格式

TCP报文由首部和数据部分组成。TCP的全部功能都体现在其首部中各字段的作用,TCP首部前20个字节是固定的,后面有4n字节可根据需要选择,此处只介绍与其可靠传输有关的部分。TCP首部格式如下图所示:
TCP报文首部格式

  • 序号 占4字节,TCP面向字节流,TCP连接中每一个字节都按顺序编号,该字段指的是本报文段所发送数组的第一个字节的序号。
  • 确认号 占4字节,期望收到对方下一个报文段的第一个数据字节的序号。比如B受到了A发送的报文段,序号为501,长度为200,则B向A发送的报文中确认号应为700。确认号为N,则说明序号到N-1的 数据全部正确收到。
  • ACK 确认字段。当ACK=1,确认号字段有效;ACK=0 ,确认号无效。TCP连接建立后所有报文段ACK置1.
  • SYN 同步字段,建立时用于同步序号。SYN=1,ACK=0表示是一个连接请求报文段;若对方同意,响应报文为SYN=1,ACK=1.
  • FIN 终止字段,当FIN=1时,要求释放运输连接。
  • 窗口 占2字节,指的是发送本报文段的一方的接收窗,告诉对方从本报文段首部的确认号算起,接收方目前允许对方发送的数据量,对方依次设置发送窗口。这个字段与拥塞避免和流量控制有密切关系。
  • 校验和 占2字节,检验首部和数据部分.

2.滑动窗口与连续ARQ

(1)以字节为单位的滑动窗口

TCP的滑动窗口以字节为单位,用一个简单地例子说明滑动窗口的工作原理,假定数据单向的从A向B发送(A发送数据,B给出确认)。
假定A受到了B发来的确认,窗口为20字节,确认号为31,则A构造出如下图的发送窗口。在未收到B确认之前,A可以将发送窗口的内容连续发送,且已发送的数据暂时保留用以重传。发送窗口后沿后的部分已收到确认,不需保留,故后沿是不可能后移的;发送窗口前沿前面部分不允许发送,超出了B的接受空间。后沿由确认号决定,前沿由确认号、窗口大小和拥塞程度决定
发送窗口
如图所示,假定A发送了31~37的数据,则可用三个指针确定窗口:P3-P1 = A的发送窗口;P2-P1=已发送但尚未收到确认的序号;P3-P2=允许发送但当前未发送的字节数。
而B维持一个接受窗口,接收窗口必须大于等于A的发送窗口,且B只对按序收到的最后一个字节的序号给出确认,如下图所示。虽然B接受到了序号为33、34、35的数据,但并不是按序接受,所以不能发送确认。当B依次接受到了32、31就可以使接收窗口向前移动5个字节同时发送确认号为36的报文,使得A发送窗口后沿和前沿前移(P1移动到36)。
在这里插入图片描述
A的发送窗口并不总是与B的接收窗口等大,还收到网络拥塞的影响;不按序到达的数据一般不能直接丢弃而是暂存到接收缓存已提高网络效率;接收方B具有累计确认的功能,可以在发送自己的数据时“捎带”确认。

(2)重传机制

TCP的发送方在规定时间内没有收到确认就要重传已发送的报文段,为此给每个发送的报文都设计一个超时计时器。
首先TCP用自适应算法计算报文段的往返时间RTT(报文发出时间与收到确认时间的差),并保留加权平均往返时间 R T T S RTT_S RTTS,第一次计算时 R T T S RTT_S RTTS即为实际的RTT,后续按如下公式计算,其中α权值推荐为1/8: 新 的 R T T s = ( 1 − α ) × ( 旧 的 R T T S ) + α × ( 新 的 R T T 样 本 ) 新的RTT_s=(1-\alpha)\times(旧的RTT_S)+\alpha\times(新的RTT样本) RTTs=(1α)×(RTTS)+α×(RTT)  超时重传时间RTO应略大于上述时间: R T O = R T T S + 4 × R T T D RTO=RTT_S+4 \times RTT_D RTO=RTTS+4×RTTD
  其中RTTD指的是RTT的偏差的加权平均值,它与RTTS和新的RTT的样本之差有关,第一次时 R T T D RTT_D RTTD取RTT样本值的一般,后续按以下公式计算,其中β设为1/4:
新 的 R T T D = ( 1 − β ) × ( 旧 的 R T T D ) + β × ∣ R T T S − 新 的 R T T 样 本 ∣ 新的RTT_D=(1-\beta)\times(旧的RTT_D)+\beta \times \left| RTT_S-新的RTT样本 \right| RTTD=(1β)×(RTTD)+β×RTTSRTT  考虑两种特殊情况。若B发送的确认丢失了,那A在超时计时器到期后就重传报文,假定B又受到了该报文,那么B应当直接丢弃该报文并且重新向A发送确认(因为A未收到确认),如下图左所示。
  如下图右所示,若B对分组的确认迟到了,A重传后会受到重复的确认,A应当丢弃重复的确认,B受到重复的报文后要丢弃该报文但必须重新发送分组。

重传示意图

3.流量控制

  TCP的流量控制是利用滑动窗口实现的,可以控制发送发的发送速率使得接收方来得及接受。接收方B可以在确认报文中更改窗口字段的值实现流量控制。若B设置窗口为0,那么发送方A就会停止发送直至获得一个新的窗口值。
  考虑一种特殊情况,如果B发送完零窗口报文后发送的非零窗口报文丢失,那么A、B双方会陷入互相等待的死锁局面。为此必须设置一个死锁避免机制,TCP协议的做法是为每个连接设计一个持续计时器,当有一方收到零窗口通知时,就启动该计时器

4.拥塞控制

  拥塞控制与流量控制关系密切,拥塞控制的目的是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载,是一个全局控制的过程(流量控制是点对点通信量的控制)。拥塞是一个非常复杂的过程,因为拥塞的瓶颈会转移所以必须平衡整个系统才能解决。若频繁的进行拥塞控制,那么相关的控制报文会加剧网络的震荡;若过于迟缓地行动又无法达到控制效果,必须采取一个这种方案。TCP进行拥塞控制的算法有四种:慢开始、拥塞避免、快重传和快恢复。
  TCP的拥塞控制也是基于窗口的,假定接收方总是有足够大的缓存空间,发送窗口的大小由拥塞窗口决定。

(1)慢开始

  连接刚建立时,主机不清楚网络的拥塞情况,此时不能直接将大量数据注入网络,执行慢开始算法逐渐增大拥塞窗口。同理,发生超时重传时也要执行慢开始算法。拥塞窗口cwnd初始值设置为不超过2至4个SMSS的值(发送方最大报文段)。每收到一个报文段的确认,cwnd即可增加: m i n ( N , S M S S ) min(N,SMSS) min(N,SMSS)其中N指的是原先未被确认、但现在被刚收到的确认报文段所确认的字节数。
  开始时发送方设cwnd=1,发送第一个报文M1。当收到M1的确认后,将cwnd增大为2,接着发送M2和M3两个报文……最终显现的效果是,没经过一个传输轮次拥塞窗口大小就加倍(在一个传输轮次中发送方将cwnd所允许发送的所有报文段都连续发送出去并收到了最后一个字节的确认)。如下图所示:
在这里插入图片描述
  此处以报文段数量作为cwnd的单位,实际上cwnd的单位为字节。且在TCP实际运行中,cwnd不是等到一个传输轮次结束再加倍,而是每接收到一个报文的确认就增大1,这样发送方就可以直接发送新的报文段而不需要等这个轮次的确认都收到,这种流水线式的运行方式提高了传输效率。

(2)拥塞避免

 为防止cwnd增长过大引起网络拥塞,设置一个慢开始门限ssthresh变量:cwnd<ssthresh时,使用慢开始算法;cwnd>ssthresh时,使用拥塞避免算法;cwnd=ssthresh时,既可以进行慢开始也可以进行拥塞避免。
 发生超时重传时要及时调整门限值,令ssthresh=cwnd/2。
 拥塞避免算法使得cwnd随传输轮次线性增大(而不是指数增大),每经过一个往返时间RTT就令cwnd增加1。

(3)快重传

当发送方连续收到了3个对同一报文的确认时,执行快重传,立即将接收方所期望的报文段重传。这时候,网络并未发生拥塞只是丢了个别报文段,如果使用慢开始将cwnd设为1会降低网络传输效率。而快重传算法可以让发送方及时知道个别报文段的丢失,这要求接收方不采用捎带确认机制,而是立即发送确认,并且在收失序报文段时要发送对已收到报文段的重复确认。快重传可以使整个网络的吞吐量提升约20%,具体过程如下:
在这里插入图片描述

(4)快恢复

  在连续收到3个重复的确认之后,发送方知道只发生了个别报文段的丢失,此时使用快恢复算法,令ssthresh=cwnd/2,cwnd=ssthresh,并开始执行拥塞避免算法。
  实际上,接收方的缓存空间时有限的,从端对端的流量控制角度考虑,发送方的发送窗口不能超过对方给出的窗口值rwnd,故实际上的发送窗口应当取rwnd和cwnd的较小值。

拥塞避免的完整流程图如下所示:
拥塞控制流程图

TCP运输连接

(1)TCP连接的建立

建立连接过程要交换三个TCP报文段,称为三报文握手。如下图所示,A为客户机,B为服务器,A主动打开连接而B被动打开连接。
TCP连接建立
具体过程为:

  • ①B的TCP服务器进程创建传输控制块TCB,进入LISTEN(收听)状态,准备接受客户的连接请求。
  • ②A向B发送链接请求报文,置SYN为1,选择一个初始序号x,该报文不携带数据,但要消耗掉一个序号。客户端进入SYN-SENT(同步已发送)状态,等待B的确认报文。
  • ③B收到链接请求报文后,若同意连接则向A发送一个确认报文,将SYN和ACK都置为1,确认号为x+1。同时B给出自己数据的初始序号y。该报文不携带数据,但也消耗一个序号,并使B进入SYN-RCVD(同步收到状态)。
  • ④A收到B的确认后,再向B给出确认,ACK=1,seq=x+1,ack=y+1,该报文可以携带数据,也可以不携带数据,不携带数据时该报文不消耗序号。发出后A进入ESTABLISHED(已建立连接)状态,B收到该报文后也进入ESTABLISHED状态,双方可以开始进行数据交换。
    使用该报文的目的是为了防止已失效的连接请求报文传送到B,使得B错误的进入SYN-RCVD状态,一直等待A的回应(此时A未发出建立连接请求不会回应)而浪费资源。

(2)TCP连接的释放

连接释放的过程较复杂,因为一方提出终止后,另一方的数据可能未发送完毕,必须进行四次报文交换。数据传输结束后任何一方都可以终止连接。假定A是发起终止的一方,如下图所示:
TCP连接释放
具体过程为:

  • ①A进程发送连接释放报文,置FIN=1,seq=u,u是前面传输数据的最后一个自己的序号加1,并停止发送数据(主动关闭)。而后,A进入FIN-WAIT-1(终止等待1)状态。FIN即使无数据也消耗一个序号。

  • ②B收到连接释放报文后,发送确认,置ACK=1,ack=u+1,seq=v(获得方式同u),而后B进入CLOSE-WAIT(关闭等待)状态。这时候要通知应用程序,告知TCP连接处于半关闭状态,A无数据发送,但B可能还有数据没有发完。

  • ③A收到确认后,进入FIN-WAIT-2(终止等待2)状态,继续接受B的数据,并等待B发送连接释放报文。

  • ④B剩余数据发送完后,向A发送连接释放报文段,置FIN=1,ACK=1,ack=u+1(A没有发送数据,确认号不变),seq=w(B可能又发了一些数据),而后B进入了LAST-ACK(最后确认)状态,等待A的确认。

  • ⑤A收到B的连接释放报文后,发送确认,置ACK=1,seq=u+1,ack=w+1(FIN报文消耗一个序号),而后进入了TIME-WAIT(时间等待)状态。此时,TCP连接并未释放,需要再等待2MSL才能进入CLOSED状态。此处MSL指的是最长报文寿命,用时间等待计时器完成该步骤。
    设置TIME-WAIT状态的原因有两个:保证A发送的ACK报文段能到达B,若超时A可以重新发送,防止B始终无法关闭;防止“已失效的连接请求报文段”出现在本连接中,等待2MSL可以使得本次连接所有的报文段都从网络中消失。

  • ⑥B收到A的确认后,进入关闭状态。

    此外,TCP还为连接设置了一个保活计时器,使得当一方故障时,另一方不会无限期地等待。服务器每次收到客户数据,就重置保活计时器,若保活计时器归零,则发送探测报文,连续多个探测报文未回应,则关闭连接。

  • 4
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值