TCP协议

TCP是一个可靠的,面向连接的传输层协议

组成

  • 一台主机上的缓存(包括发送,接收缓存),变量,与另一个进程连接的套接字
  • 另一台主机上的缓存(包括发送,接收缓存),变量,与另一个进程连接的套接字

报文结构

  • 序号

当要发送的数据大小超过MSS时,数据会分包,每个包就需要有序号来标明先后顺序;初始序号时随机选择的,防止碰撞旧连接

  • 确认号

确认发出方希望接受到的下一字节的序号

超时相关

RTT: 往返时间

SampleRTT

EstimatedRTT = 0.875 * EstimatedRTT + 0.125 * SampleRTT

DevRTT

TimeoutInterval(超时间隔) = EstimatedRTT + 4*DevRTT

重传

每次超时时,TCP重传具有最小序号的还未被确认的报文段

ACK

  • 累计确认

某一方发出ACK为N的报文,则代表序号小于等于N的数据都收到了; 接收方攒一批有序报文段,一次性确认,一批里每个最多等待500ms

  • 冗余ACK

当比期望序号大的失序报文到达时,检测出数据流中的间隔,立即发送冗余ACK,指明我期待的下一个序号

  • 快速重传

一旦接收到3个冗余ACK,TCP就执行快速重传,即赶在超时定时器之前,重传报文段

流量控制

使发送方的发送速率和接收方应用程序的读速率相匹配,防止把TCP连接两端的缓冲区撑爆

  • 接收窗口

对于接收方,RecvWindow = RecvBuffer - [LastByteRecv - LastByteRead] 对于发送方,LastByteSent - LastByteAcked <= RecvWindow

在 TCP 协议中,接收端的窗口的起始点是下一个要接收并且 ACK 的包,即便后来的包都到 了,放在缓存里面,窗口也不能右移,因为 TCP 的 ACK 机制是基于序列号的累计应答,一旦 ACK 了一 个系列号,就说明前面的都到了,所以只要前面的没到,后面的到了也不能 ACK,就会导致后面的到 了,也有可能超时重传,浪费带宽。

  • 空闲通知

接收方的缓存区从满到有空闲时,需要在ACK里告诉发送方

拥塞控制

网络上路由器的传输容量时有限的,缓存区也是有限的,缓存超了就丢掉了,操作系统默认的拥塞控制算法Reno

拥塞控制算法需要解决三个问题

  1. TCP发送方如何限制它向其连接发送流量的速率

通过传递一个叫拥塞窗口CongWin的变量,对于发送方,LastByteSent - LastByteAcked <= {CongWin, RecvWindow}, 拥塞控制的思想就是通过减小其拥塞窗口的大小,降低其发送速率

  1. 二是发送方如何感知其到目的地之间的路径存在拥塞

要么出现超时,要么出现来自接收方的三个冗余ACK

  1. 发现拥塞之后用什么算法来改变其发送速率

    • 加性增

    每次收到一个确认后就把CongWin增大一点,其目标是在每个RTT内CongWin增加一个MSS

    • 乘性减

    每一次发现丢包就把拥塞窗口的大小减半,最后不能低于一个MSS

    • 慢启动

    TCP连接开始时,CongWin的初始值为一个MSS;每当一个传输的报文段被确认后,CongWin指数型增长;当发生超时时,重新进入慢启动阶段,CongWin又置为一个MSS