TCP/IP协议族的传输层基础(6)——TCP协议提高性能的机制

TCP采用下面的方式来提供传输的性能

  • 滑动窗口
  • 快速重传
  • 延迟应答
  • 捎带应答
首先介绍一下TCP的发送缓冲区和接收缓冲区,这是TCP面向字节流的保障
创建一个TCP的socket,同时会在内核中创建一个发送缓冲区接收缓冲区
  • 调用write时,数据会先写入发送缓冲区中
  • 如果发送的字节数太长,会被拆分成多个TCP的数据包发出
  • 如果发送的数据太短,就会先在缓冲区里等待,等待缓冲区长度差不多了,或者其他合适的时机发送出去
  • 接收数据的时候,数据也是从网卡驱动程序到达内核的接收缓冲区
  • 然后应用程序可以调用read从接收缓冲区拿数据
  • TCP的一个连接,既有发送缓冲区,又有接收缓冲区,这叫全双工

粘包问题
  • 粘包问题中的包,指的是应用层的数据包
  • 在TCP协议头中,没有UDP一样的报文长度的字段,但有一个序号
  • 站在传输层的角度,TCP是一个报文一个报文传过来的,按照序号排好放在缓冲区中
  • 站在应用层的角度,看到的只是一串连续的字节数据
  • 那么应用层看到这么一串字节数据,就不知道从哪个部分开始到哪个部分是一个完整的应用层数据包
避免粘包问题——明确两个包的边界
  • 对于定长的包, 保证每次都按固定大小读取即可, 从缓冲区从头开始按sizeof()依次读取即可;
  • 对于变长的包,可以在包头位置,约定一个包总长度的字段,从而就知道了包结束的位置(比如HTTP协议中在头部字段中有一个描述body部分长度的字段Content-Length)
  • 对于变长的包,还可以再包和包之间使用明确的分隔符(应用层协议,是程序员自己决定,只要保证分隔符不和正文冲突,比如HTTP协议对于头部和body部分就用一个空行分隔)
UDP并不会出现粘包的问题,它是一个一个发送数据包的,不会半个半个这样发。

滑动窗口
    可以想象,如果发送端每次发送一个包,都必须要等接收端发送一个确认应答的包之后才能继续发下一个包,这样的效率是非常的低的,性能很差,尤其是在数据往返的时间较长的时候。
     因此,既然这样一发一收的机制效率很低,我们就一次多发送几条数据,就可以大大提高性能(其实是将多个段的等待时候重叠在一起了)。
       
  • 窗口大小指的是无需等待可以一次性发送的数据的最大值。下图的窗口大小就是4000个字节(4个段)
  • 注意这个窗口大小不是TCP头部那个16位窗口大小,那个是指的接收缓冲区的大小,而这里的窗口大小指的是一次能发送的数据段的窗口大小
  • 发送前4个段的时候,不需要等待ACK,直接发送
  • 收到第一个ACK后,滑动窗口向后移动,继续发送第五个段的数据;以此类推
  • 操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区来记录当前还有哪些数据没有应答;只有确认应答过的数据,才能从缓冲区删掉
  • 窗口越大,则吞吐率越高                         
                      TCP/IP协议族的传输层基础(6)——TCP协议提高性能的机制              
那么出现了丢包怎么办呢?怎么进行重传
情况一:数据包已经抵达,ACK丢包了                            
这种情况下,部分ACK丢了并不要紧,因为可以通过后续的ACK进行确认

情况二:数据包直接丢了
TCP/IP协议族的传输层基础(6)——TCP协议提高性能的机制
  • 当某一报文段直接丢失之后,发送端会一直收到“下一个是1001”这样的ACK,就像是在提醒发送端“我想要的是1001”一样
  • 如果发送端主机连续三次收到了同样一个“1001”这样的应答,就会对数据1001-2000这个段进行重新发送
  • 这个时候接收端收到了1001之后,再次返回的ACK就不是2001了,就是7001了,因为2001-7000的数据段接收端已经接收到了,被放到了接收端操作系统内核的接收缓冲区
这样的机制叫做“快速重传”机制

延迟应答
如果接收端的主机立刻返回ACK应答,这个时候可能返回的窗口可能比较小(这个窗口指的是发送缓冲区的大小,不同于上面的滑动窗口,是TCP头部信息的固定的16位窗口大小字段)
  • 假设接收缓冲区为1M,一次收了500K数据;如果立刻应答,返回的窗口就是500K
  • 但实际上处理数据的速度可能很快,10ms之内就把500K数据处理完了
  • 在这种情况下,接收端处理还远没有达到自己的极限,即使窗口再放大一点,也能够处理
  • 如果接收端延迟一会应答,比如再等待20ms应答,那么这个时候返回的窗口大小就是1M

为了要保证窗口量尽量越大,吞吐量越大,延迟应答是一定要做到的。
但是延迟应答也会有一个限制
  • 数量限制:每隔N个包应答一次(一般N取2)
  • 时间限制:超过最大延迟时间就应答一次(一般最大延迟时间取200ms)
                            TCP/IP协议族的传输层基础(6)——TCP协议提高性能的机制

捎带应答
在想要发送的数据的基础上再发送一个确认应答,最典型的就是(四次挥手变成了三次挥手,前面的文章都有讲到,被动关闭连接的一端发送FIN结束报文段的时候可能会捎上对主动关闭连接的一端的结束报文段的ACK确认应答)
                  TCP/IP协议族的传输层基础(6)——TCP协议提高性能的机制