TCP要点总结

TCP要点

  1. 有连接
  2. 可靠传输
  3. 端到端流量控制
  4. 数据按序到达

TCP报文格式

TCP要点总结_第1张图片

  1. Sequence Number: TCP段的序列号,解决TCP的乱序问题
  2. Acknowledgement Number: 确认号,表明接收端期望收到源端的下一个数据字节,解决TCP的不丢包可靠性问题
  3. TCP Flags: 标志位字段RST/PSH/SYN/FIN/ACK,表明Segment的类型,用于操控TCP的状态机
  4. Advised-Window: 滑动窗口大小,值为当前缓冲区的拥塞程度有关,告知发送端接收端可以接收的大小,解决流量控制问题

TCP状态机

TCP C/S交互过程(3次握手4次挥手)

TCP要点总结_第2张图片
4次挥手是因为防止被请求断开的一方还有数据未发送完,必须两个方向都没有数据发送才能断开TCP连接。3次握手因为没有建立连接时并没有数据需要传输,所以可以SYN和ACK包同时发送

SN初始化问题

TCP中的ISN和一个伪时钟绑定,每4微秒进行加1操作,直至超过2^32,又重新回到0,大概4.5小时。只要MSL不超过4.5小时,就不会出现重复ISN的问题。

Time_Wait状态 & Time-Wait Timer

Time_Wait设为两个MSL,主要是为了确保最后一个Fin对应的ACK能被接收,如果ACK丢失重发FIN仍能被接收到,再发ACK确认消息,防止FIN重发影响新连接的问题。这里的新连接是指与旧连接5元素相同的连接。Time_Wait阶段会产生一个时间等待计时器。
如果Server中Time_wait状态连接数过多,可以通过减小tcp_fin_timeout来快速释放请求。对于使用tcp_tw_reuse和tcp_tw_recycle两个参数的方法需要谨慎,可能会干扰新连接。也可以通过让客户端主动断开连接的方式将Time_wait状态转移到client端

建立连接SYN超时,SYN Flood攻击

在Server接收到SYN包之后,如果回了SYN+ACK包,但是Client掉线了,则该连接会处于中间状态,默认重试发送5次(每次时间间隔增加2倍),如果仍未收到ACK,则断开连接。SYN FLOOD攻击即利用SYN+ACK重发的情况,让服务器的SYN连接队列耗尽。可以通过设置最大等待处于客户端还没有应答回来的连接数tcp_max_syn_backlog,或者tcp_abort_on_overflow直接拒绝多余连接

Keepalive Timer 保活计时器

每当收到一个报文,KeepAlive Timer就重置。一般如果超过两个小时没有数据传输,就会发送探测报文段(75s发送一个),如果10个以后仍然没有响应,则终止连接。保活计时器是主要为了防止TCP连接出现长时间的空闲。

TCP可靠性和数据按序到达

TCP主要依靠Sequence Number和ACK Number来保证可靠性和数据的有序。

TCP超时机制 & Retransmission Timer 超时计时器

TCP中的RTT(round trip time),即一个数据包发送到确认的时间,利用报文中的时间戳来计算。RTO(Retransmission Timeout)就是通过RTT来计算的。粗略算法是根据RTT的偏差,再以变化率作为自变量来计算RTO。为了减小开销,每个连接才有一个超时计时器。有一套简单的规则:

1. 发送一个TCP报文时,如果没有超时计时器,则开启
2. 发送一个TCP报文时,如果有超时计时器,则不在开启
3. 接收一个非冗余ACK时,如果有数据在传输过程中,则开启Timer
4. 接收一个非冗余ACK时,如果没有数据在传输过程中,则关闭Timer

规则3有效的保证了数据不会被过早的重传。

乱序数据缓存和选择确认

ACK只会确认连续发送的TCP报文的最后一个数据序列。在早期的TCP实现中,如果发生丢失,Sender会重传丢失序列后的所有数据序列,这可能会产生重传风暴。现在数据传输过程中,Receiver会缓存乱序到来的字段,然后告诉Sender哪些序列缺失了(DACK算法和FACK算法)。

序列号回绕问题

因为序列号只有32个bit,如果达到最大值,序列号即重新从0开始,这会产生回绕问题。如果缓冲区中序列号产生了回绕,TCP会检测时间戳,通过时间戳来纠正序列号的顺序。时间戳同样可以解决ISN初始化的问题。

TCP流量控制

TCP流量控制主要是通过滑动窗口来实现的。TCP报文头部有一个Window窗口值,表示接收端当前可以接收数据的大小。在建立连接的时候,双方会协商最大的窗口值,传输过程中再根据缓冲区可用大小动态更新。滑动窗口可看做是一个循环队列中一部分。

TCP要点总结_第3张图片

  • 接收端,LastedByteRead指向TCP正在读取的位置,NextByteExpected表示收到连续包的最后一个位置,LastByteRcvd指向收到的包的最后一个位置,中间有些数据没有到达,留白。接收端会在发给发送端的ACK确认报文中报告Window的大小,即MaxRcvBuffer - LastByteRcvd - 1
  • 发送端也有三个位置,分别表示已经被确认了的包的位置,LastByteSent表示发出但未被接收端ACK确认的最后位置,LastByteWritten指向被上层应用正在写的位置。

TCP要点总结_第4张图片
上图为滑动窗口示意图。

Zero Window & 持久计时器 Persistent Timer

当接收端缓存区已满时,会发送一个零窗口的通知。发送端接收到零窗口通知后,就会启动Persistent Timer,每隔一段时间就会发送一个特殊的报文段,该报文段只有一个字节,且序号永远不会被确认。时间间隔是在上次的间隔基础上加倍,直至60S之后保持60S不变,3次之后,一些TCP实现就会断开连接。**每一个连接只有一个持久计时器。即便在零窗口状态下,TCP规定,仍要接收零窗口探测报文段、确认报文段,携带紧急数据的报文段。##

糊涂窗口综合征 Silly Window Syndrome

当接收端或发送端处理数据过慢时,可能每次发送的TCP报文只有几个字节,极大的浪费了带宽(TCP+IP头部共有40个字节)。以太网的MTU为1500字节,除去TCP+IP头部,传输数据的字节就只有1460,这就是MSS(Max Segment Size)。

  • 对于接收端,可以采用Clark方法。如果某个时候缓冲区可用大小小于某个值,则发送ACK(窗口为0)的报文,这样就阻止了Sender继续发送数据。当Receiver处理数据后,Buffer可用的大小大于MSS或者Buffer有一半为空,就发送正常的窗口大小ACK报文,使得Sender可以传送数据过来。
  • 对于发送端,可以采用Nagle方法。标准的Nagle方法可以用两个情况说明:

    1. 当前窗口和数据大小都大于MSS,则发送报文
    2. 如果当前没有不足MSS大小的报文未被确认,则发送报文,否则等待报文满足情况1或者不足MSS大小的报文被确认

    Nagle算法可以通过设置tcp_nodelay来关闭。

TCP拥塞控制

TCP拥塞控制体现了TCP协议的公平性,以牺牲自我来防止网络阻塞。这有一部分原因是因为IP比较简单,只是尽其所能传送IP包达到指定点。
TCP拥塞控制主要有四个方法:慢开始,拥塞避免,快速重传和快速恢复。
TCP要点总结_第5张图片

  • 慢开始
    1. 当一个连接开始后,初始化cwnd(congestion window)为1
    2. 每收到一个ack,cwnd=cwnd+1,线性上升
    3. 每过一个RTT时间,cwnd=cwnd*2,指数上升
    4. 当cwnd>=ssthresh(slow start threshold慢启动阀值),进入“拥塞避免”算法
  • 拥塞避免
    1. 收到一个ACK,cwnd=cwnd+1/cwnd
    2. 每过一个RTT时间,cwnd=cwnd+1
  • 快速重传
    当连续收到三个重复确认后(发生此种情况,Sender认为网络并没有阻塞,可能是其他原因导致包丢失),Sender马上发送Receiver缺失的报文段,而不用等到RTO超时。
    如果是RTO超时,则直接重新进入慢开始阶段,ssthresh=cwnd/2,cwnd=1.
  • 快速恢复
    快速恢复算法是和慢开始搭配的算法。当收到连续三个重复确认的算法后,ssthresh=cwnd/2,执行拥塞避免算法。

随机早期SED

在网络层,路由器的丢弃策略,对拥塞算法影响最大。RED(Randomearly Detection)算法过程:
路由器维持了一个队列,有两个参数:队列最小门限和最大门限。当一个分组到来时,计算队列长度:
1. 平均队列长度大于最大门限是,丢弃包
2. 平均队列长度小于最大门限大于最小门限时, 按照某一概率丢弃包
3. 平均队列长度小于最小门限,正常转发包
这样,以某一概率丢弃分组,就避免了全局的拥塞。

你可能感兴趣的:(网络)