网络基础-传输层:TCP协议详解

TCP

TCP与UDP的区别相当大。它充分的实现了数据传输时各自控制功能,可以进行丢包时的重发控制, 还可以对次序乱掉的分包进行顺序控制,而这些在UDP中都没有。此外,TCP还作为一种面向有连接的协议,只有在确认通信对端存在时才会发送数据,从而可以控制通信流量的浪费。

TCP通过以下实现可靠传输:

  • 校验和
  • 序列号
  • 确认应答
  • 重发控制
  • 连接管理
  • 窗口控制

通过序列号与确认应答提高可靠性

在TCP中,通常发送端的数据到达主机时,接收端会返回一个已收到的通知。这个消息叫做确认应答。(ACK)
其实也不难理解,有点像是我们日常对话时,在说话时中间的停顿可以点头或询问对话内容。比如,你给你的同伴说了一个笑话,她听懂了给你回了一个“嗯”,相当于给你发了一个确认应当ACK;她没听懂时,给你回了一个“咦”,就相当于给你发了一个否定确认应答NACK。
这里写图片描述

如果发送端没有接收到确认应答,那么数据丢失的可能性很大。
在一定时间内没有等到确认应答,发送端就可以认为数据已经丢失,并进行重发。由此,即使数据发生了丢包,也能保证可靠传输。
这里写图片描述

未收到确认应答也并不意味着数据一定丢失,也有可能是数据对方已经收到,但是返回的确认应答在途中丢失。这种情况也会导致发送端因没有收到确认应答,而认为数据没有到达目的地,从而进行重新发送。
这里写图片描述

但是这样其实就会出现一个问题,目标主机可能会反复收到相同数据。所以就必须有一种机制,能够识别是否已经接收到该数据,又能够识别是否需要接受。
以上可以通过序列号实现。
序列号:是按顺序给发送数据的每一个字节都标上号码的编号。
初始值也并不是0,而是在建立连接之后随机生成。接收端查询接收数据TCP首部中的序列号和数据的长度,将自己下一个应该接收到的序列号作为确认应答返送回去。

重发超时

在确认应答中提到在一个特定的时间间隔内未收到确认应答而重新发送数据。
那么这个特定时间如何确定?

  • Linux中(BSD的unix以及windows),超时以0.5s为一个单位控制,每次判定超时重发的超时时间都是0.5s的整数倍。
  • 如果重发一次后,仍然得不到应答,等待2*0.5s后进行重传
  • 如果仍然等不到响应,则在等到4*0.5s之后重传,以次类推,以指数形式增长。
  • 累积到一定的重传次数,TCP认为网络或者对端主机发生异常,强制关闭连接。

连接管理

TCP在数据通信之前,通过TCP首部发送一个SYN包作为建立连接的请求等待确认应答(客户端)。如果对端发来确认应答,则认为可以数据通信(服务端)。如果对端的确认应答未能到达,就不会进行数据通信。

这里写图片描述

以上:建立连接的过程被称作三次握手
断开连接的过程称为四次挥手。

利用窗口控制提高速度

TCP是以一个段为单位,每发一个段进行一次确认应答的处理,这样传输方式有一个缺点,报的往返时间越长通信性能就越低。
为解决这个问题,引入了窗口这一概念。发送端主机在发送完数据之后,不需要一直等待确认应答,而是可以继续发送。
窗口大小就是指无需等待确认应答而可以继续发送数据的最大值。
这个机制实现了使用大量的缓冲区,通过对多个段同时进行确认应答功能。

这里写图片描述

如上图所示,图一如果此时收到一个序列号为2001的确认应答时,那么2001之前的数据就没有必要进行重发,这部分数据就可以过滤掉,滑动窗口变成图3的形式。

窗口控制与重发控制


使用窗口控制时,即使确认应答未能返回,数据已经被收到,是不需要被重新发送的。即使有小部分确认应答丢失也不会进行数据重发。可以通过下一个确认应答进行确认。
当某一报文段丢失之后,发送端会一直收到序号为1001的确认应答,这个确认应答好像再提醒发送端“我想接受的是从1001开始的数据”。而发送端发现如果连续三次收到同一个确认应答,就会将其所对应的数45据进行重发。这种机制也被称为高速重发控制。

流量控制

TCP提高一种机制可以让发送端根据接收端的实际接受能力控制发送的数据量。具体操作是,接收端主机向发送端主机通知自己可以接收数据的大小,于是发送端发送不超过这个限度的数据。该大小限度就是窗口大小。由接收端主机决定的。
当接收端的这个缓冲区一旦面临数据溢出时,窗口大小的值也会 随之被设置为一个更小的值通知给发送端,从而控制数据发送。量。这就是一个完善的TCP流控制。
一旦缓冲区即满时,不得不暂时停止接收数据,之后,在收到发送窗口更新通知后通信才得以继续进行。如果这个窗口的更新通知在传送途中丢失了,发送端主机会时不时的发送一个叫做窗口探测的数据段,此数据段仅含一个字节以获取最新的窗口大小信息。

拥塞控制

基于窗口控制,收发主机之间能够连续发送大量数据包,然而,在通信一开始就发送大量数据,也可能会引发其他问题。
在网络拥堵时,如果突然发送一个较大量的数据,极有可能导致整个网络的瘫痪。
为了防止这种情况出现,在通信一开始时就会通过一个叫做慢启动的算法得到的数值,对发送数据量进行控制。
通俗的说,先发少量的的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据。

所以,TCP就引入了一个个概念叫拥塞窗口

  • 发送开始时,定义拥塞窗口为1
  • 每次收到ACK,拥塞窗口加1
  • 每次发送数据时,将拥塞窗口和接收端主机反馈的窗口大小做比较,取较小的值作为实际发送的窗口

像这样的拥塞窗口实际上是以指数级别增长的,为了不增长的那么快,不能使拥塞窗口单纯的加倍。此处就要引入慢启动的阈值
当拥塞窗口的数量超过这个阈值时,不再按照这个指数级别增长,而是按照线性方式增长。

  • 当TCP通信开始时,并没有设置相应的慢启动阈值。而是在超时重发时,才会设置为当时拥塞窗口的一半大小。
  • 当TCP通信开始以后,网络吞吐量会逐渐上升,但是随着网络拥堵的发生吞吐量也会急剧下降。于是会再次进入吞吐量慢慢上升的过程。因此所谓TCP的吞吐量的特点就好像是在逐步占领网络带宽的感觉。

猜你喜欢

转载自blog.csdn.net/mxrrr_sunshine/article/details/80266467