TCP(下)

195 阅读6分钟

看得见的TCP

TCP三次握手和四次挥手

image.png

image.png

服务端将ACK和FIN合并一起发送,变成了“三次挥手”。

通常情况下,服务端收到客户端的FIN时,很可能还没发送完数据; 所以就会先回复客户端ACK。

image.png

TCP三次握手异常情况

TCP第一次握手的SYN丢包

image.png

超时时间RTO翻倍;当超过最大重传次数(tcp-syn-retries)后,客户端不再发送SYN包。

TCP第二次握手的SYN、ACK丢包

image.png

客户端会重传SYN包; 服务端会重传SYN-ACK包; 服务端收到客户端重传的SYN包后,超时定时器重新计时。

SYN-ACK最大重传次数:tcp-synack-retries

TCP第三次握手的ACK丢包

image.png

  • 服务端重传SYN-ACK包超过了最大重传次数,断开连接;
  • 客户端向服务端发送数据包,超时重传15次后,断开连接。

TCP建立连接后的数据包最大超时重传次数:tcp-retries

若客户端不发送数据,什么时候会断开处于ESTABLISHED状态的连接?

TCP的保活机制。

发现死亡连接时间=保活时间+检验间隔X检验次数

TCP快速建立连接

image.png

image.png

TCP重复确认和快速重传

TCP流量控制

发送窗口=min(拥塞窗口,接收窗口)

发送窗口决定了一口气能发多少字节,MSS决定了这些字节要分多少包发完。

TCP延迟确认与Nagle算法

Nagle算法

image.png

Nagle算法最开始时一定会有一个小报文。

延迟确认

image.png


当延迟确认和Nale算法混合使用时,会产生新问题

image.png

两个同时使用会造成额外的时延。

TCP半连接队列和全连接队列

image.png

丢弃连接请求:

image.png

  1. 若半连接队列满了,并且没有开启tcp-syncookies,则会丢弃;
  2. 如全连接队列满了,且没有重传SYN+ACK包的连接请求多于1个,则会丢弃;
  3. 若没有开启tcp-syncookies,并且 max_syn_backlog 减去 当前半连接队列⻓度⼩于(max_syn_backlog >> 2),则会丢弃;
SYN半连接队列已满,只能丢弃连接吗?

开启syncookies。

image.png

服务端根据当前状态计算出一个值,放在SYN+ACK中发出; 当客户端返回ACK报文时,取出该值验证; 若合法,就认为连接建立成功。

如何防御SYN攻击?
  • 增大半连接队列
  • 开启tcp-syncookies 功能
  • 减少SYN+ACK重传次数

当服务端收到SYN攻击时,就会有大量处于SYN-REVC状态的TCP连接; 处于这个状态的TCP会重传SYN+ACK,当重传次数达到上限后,就会断开连接。

我们可以减少SYN-ACK重传次数,加快TCP连接断开。

TCP内核参数

TCP三次握手的性能提升

客户端的优化

调整SYN报文的重传次数

服务端的优化

1. 调整SYN半连接队列长度

若半连接队列已满,只能丢弃连接吗?

2. 开启syncookies功能

3. 调整SYN—ACK报文的重传次数

4. 调整全连接队列长度

若全连接队列已满,只能丢弃连接吗?

我们还可以选择向客户端发送RST。 但是,应对突发流量时,直接扔掉客户端发来的ACK仍是更好的选择。

image.png

绕过三次握手

开启Fast Open功能

image.png

TCP四次挥手的性能提升

image.png

主动方的优化

主动方:主动发起FIN断开连接的一方。


主动发送FIN报文后,连接就处于FIN-WAIT1状态。 如果没有收到对方的ACK回复,则会重传FIN;可以调整FIN报文重传次数

当进程调用了close函数关闭连接,那么它就是孤儿连接。 可以调整孤儿连接的上限个数

当孤儿连接数量大于上限,新增的孤儿连接将不再走4次挥手,而是直接发送RST强制关闭。


若收到ACK报文,连接就进入FIN—WAIT2状态;

  • 若这是close函数关闭的连接,可以:1. 调整FIN-WAIT2状态的时间;(若还没有收到FIN,连接会直接关闭)
  • 反之,是shutdown函数关闭的连接,不受此参数限制。

当主动方接收到FIN,并返回ACK,主动方的连接就进入TIME-WAIT;可以:

1. 调整time-wait状态的上限个数; 超过上限处于time-wait状态的连接会被直接关闭。

2. 复用time-wait状态的连接(只适用客户端);

  • 四次挥手中的最后一次ACK在网络中丢失,服务端处于LAST-ACK状态;
  • 客户端由于开启了tcp-tw-reuse,再次连接时,会复用超过1s的time-wait的连接。但客户端新发的SYN会被忽略(由于时间戳),因为服务端比较了客户端的上一个报文与SYN的时间戳,过期的报文被服务端丢弃。
  • 服务端FIN迟迟没有收到ACK,于是超时重发FIN;
  • 处于SYN-SENT的客户端,由于收到FIN,则会回RST给服务端,于是服务端离开了LAST-ACK状态;
  • 客户端SYN超时重发,与服务端重新三次握手。

被动方的优化

被动方内核在自动回复ACK后就进入CLOSE-WAIT,等待进程调用close关闭连接。因此,若出现大量CLOSE-WAIT,应从应用程序中找问题。

当被动方发送FIN报文后,连接就进入LAST-ACK状态,可以调整FIN重传次数

如果连接双方同时关闭连接?

两方发送FIN报文时,都认为自己是主动方。

image.png

TCP数据传输的性能提升

TCP连接由内核维护,内核为每个连接建立内核缓冲区:

  • 若内存配置过小,则无法充分利用带宽;
  • 若内存配置过大,容易把服务器资源耗尽。

扩大窗口大小

image.png

在TCP选项字段定义了窗口扩大因子; 要使用窗口扩大选项,主动方和被动方必须在各自的SYN中发送该选项;

调整缓冲区

缓冲区要与网络传输能力匹配。

如何计算网络传输能力?带宽时延积

image.png

发送缓冲区与带宽时延积的关系:

  • 若发送缓冲区超过带宽时延积,超出的部分无法有效传输,导致网络过载,容易丢包。
  • 若小于,则不能很好地发挥传输效率。

调节发送缓冲区范围

发送缓冲区是自行调节的; 当发送方数据被确认且没有新数据要发送时,就会释放缓冲区内存。

调节接收缓冲区范围

根据当前内存而定。

调节TCP内存范围