总结 TCP

229 阅读8分钟

TCP

特点

  • TCP是面向连接的运输层协议
  • 每一条TCP连接只能有两个端点(endpoint),每一条TCP连接只能是点对点的(一对一)
  • TCP提供可靠交付的服务。通过TCP连接传送的数据,无差错、不丢失、不重复、并且按序到达。
  • TCP提供全双工通信 。TCP允许通信双方的应用进程在任何时候都能发送数据。TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据。在发送时,应用程序在把数据传送给TCP的缓存后,就可以做自己的事,而TCP在合适的时候把数据发送出去。在接收时,TCP把收到的数据放入缓存,上层的应用进程在合适的时候读取缓存中的数据。
  • 面向字节流。TCP中的“流”(stream)指的是流入到进程或从进程流出的字节序列。

连接端点

每一条TCP连接有两个端点。那么,TCP连接的端点是什么呢?

TCP连接的端点叫做套接字(socket)或插口。根据RFC 793的定义:端口号拼接到(contatenated with) IP地址即构成了套接字。因此,套接字的表示方法是在点分十进制的IP地址后面写上端口号,中间用冒号或逗号隔开。例如,若IP地址是192.3.4.5而端口号是80,那么得到的套接字就是(192.3.4.5:80。每一条TCP连接唯一地被通信两端的两个端点(即两个套接字)所确定。即:

image.png

TCP 连接的端点是个很抽象的套接字,即(IP 地址:端口号)。也还应记住:同一个IP地址可以有多个不同的TCP连接,而同一个端口号也可以出现在多个不同的TCP连接中。

可靠传输的工作原理

利用连续ARQ协议

连续ARQ协议规定,发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置。图(b)表示发送方收到了对第1个分组的确认,于是把发送窗口向前移动一个分组的位置。如果原来已经发送了前5个分组,那么现在就可以发送窗口内的第6个分组了。

image.png

  • 接收方一般都是采用累积确认的方式。这就是说,接收方不必对收到的分组逐个发送确认,而是在收到几个分组后,对按序到达的最后一个分组发送确认,这就表示:到这个分组为止的所有分组都已正确收到了。
  • 累积确认有优点也有缺点。优点是:容易实现,即使确认丢失也不必重传。但缺点是不能向发送方反映出接收方已经正确收到的所有分组的信息。例如,如果发送方发送了前5个分组,而中间的第3个分组丢失了。这时接收方只能对前两个分组发出确认。发送方无法知道后面三个分组的下落,而只好把后面的三个分组都再重传一次。
  • 这就叫做Go-back-N(回退N),表示需要再退回来重传已发送过的N个分组。可见当通信线路质量不好时,连续ARQ协议会带来负面的影响。

TCP 流量控制

利用滑动窗口实现流量控制

所谓流量控制(flow control)就是让发送方的发送速率不要太快,要让接收方来得及接收。

例子说明如何利用滑动窗口机制进行流量控制。

image.png

我们应注意,接收方的主机B进行了三次流量控制。第一次把窗口减小到rwnd =300,第二次又减到rwnd = 100,最后减到rwnd = 0,即不允许发送方再发送数据了

现在我们考虑一种情况。在图中,B向A发送了零窗口的报文段后不久,B的接收缓存又有了一些存储空间。于是B向A发送了rwnd = 400的报文段。然而这个报文段在传送过程中丢失了。A一直等待收到B发送的非零窗口的通知,而B也一直等待A发送的数据。如果没有其他措施,这种互相等待的死锁局面将一直延续下去。

为了解决这个问题,TCP为每一个连接设有一个持续计时器(persistence timer)。只要TCP连接的一方收到对方的零窗口通知,就启动持续计时器。若持续计时器设置的时间到期,就发送一个零窗口探测报文段(仅携带1字节的数据),而对方就在确认这个探测报文段时给出了现在的窗口值[插图]。如果窗口仍然是零,那么收到这个报文段的一方就重新设置持续计时器。如果窗口不是零,那么死锁的僵局就可以打破了。

TCP 的拥塞控制

慢开始和拥塞避免

发送方维持一个叫做拥塞窗口 cwnd (congestion window)的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口。以后我们就知道,如果再考虑到接收方的接收能力,那么发送窗口还可能小于拥塞窗口。

发送方控制拥塞窗口的原则是:只要网络没有出现拥塞,拥塞窗口就再增大一些,以便把更多的分组发送出去。但只要网络出现拥塞,拥塞窗口就减小一些,以减少注入到网络中的分组数。

发送方又是如何知道网络发生了拥塞呢?我们知道,当网络发生拥塞时,路由器就要丢弃分组。因此只要发送方没有按时收到应当到达的确认报文,就可以猜想网络可能出现了拥塞。现在通信线路的传输质量一般都很好,因传输出差错而丢弃分组的概率是很小的(远小于1 %)。

慢开始算法

当主机开始发送数据时,如果立即把大量数据字节注入到网络,那么就有可能引起网络拥塞,因为现在并不清楚网络的负荷情况。经验证明,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是说,由小到大逐渐增大拥塞窗口数值。通常在刚刚开始发送报文段时,先把拥塞窗口cwnd设置为一个最大报文段MSS的数值。而在每收到一个对新的报文段的确认后,把拥塞窗口增加至多一个MSS的数值。用这样的方法逐步增大发送方的拥塞窗口cwnd,可以使分组注入到网络的速率更加合理。用慢开始算法后,每经过一个传输轮次(transmission round),拥塞窗口cwnd就加倍。

image.png 为了防止拥塞窗口cwnd增长过大引起网络拥塞,还需要设置一个慢开始门限ssthresh状态变量(如何设置ssthresh,后面还要讲)。慢开始门限ssthresh的用法如下:

  • 当cwnd < ssthresh时,使用上述的慢开始算法。
  • 当cwnd > ssthresh时,停止使用慢开始算法而改用拥塞避免算法。
  • 当cwnd = ssthresh时,既可使用慢开始算法,也可使用拥塞避免算法。 拥塞避免算法

思路是让拥塞窗口cwnd缓慢地增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍。这样,拥塞窗口cwnd 按线性规律缓慢增长,比慢开始算法的拥塞窗口增长速率缓慢得多。然后把拥塞窗口cwnd重新设置为1,执行慢开始算法。这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕。

快重传和快恢复

快重传算法

快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段M3,而不必继续等待为M3设置的重传计时器到期。由于发送方能尽早重传未被确认的报文段,因此采用快重传后可以使整个网络的吞吐量提高约20%。

image.png 快恢复算法 与快重传配合使用,其过程有以下两个要点:

  • 当发送方连续收到三个重复确认时,就执行“乘法减小”算法,把慢开始门限ssthresh减半。这是为了预防网络发生拥塞。请注意,接下去不执行慢开始算法。
  • 由于发送方现在认为网络很可能没有发生拥塞(如果网络发生了严重的拥塞,就不会一连有好几个报文段连续到达接收方,也就不会导致接收方连续发送重复确认),因此与慢开始不同之处是现在不执行慢开始算法(即拥塞窗口cwnd现在不设置为1),而是把cwnd值设置为慢开始门限ssthresh减半后的数值,然后开始执行拥塞避免算法(“加法增大”),使拥塞窗口缓慢地线性增大