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
拥塞控制算法需要解决三个问题
- TCP发送方如何限制它向其连接发送流量的速率
通过传递一个叫拥塞窗口CongWin的变量,对于发送方,LastByteSent - LastByteAcked <= {CongWin, RecvWindow}, 拥塞控制的思想就是通过减小其拥塞窗口的大小,降低其发送速率
- 二是发送方如何感知其到目的地之间的路径存在拥塞
要么出现超时,要么出现来自接收方的三个冗余ACK
-
发现拥塞之后用什么算法来改变其发送速率
- 加性增
每次收到一个确认后就把CongWin增大一点,其目标是在每个RTT内CongWin增加一个MSS
- 乘性减
每一次发现丢包就把拥塞窗口的大小减半,最后不能低于一个MSS
- 慢启动
TCP连接开始时,CongWin的初始值为一个MSS;每当一个传输的报文段被确认后,CongWin指数型增长;当发生超时时,重新进入慢启动阶段,CongWin又置为一个MSS