TCP 中的7种定时器

学习总结 TCP 中7种非常重要的定时器。

握手阶段

连接建立定时器

  当发送端发送 SYN 报文想建立一条新连接时,会开启连接建立定时器,如果没有收到对端的 SYN+ACK 包,则将进行重传。重传的次数由 /proc/sys/net/ipv4/tcp_syn_retries 决定,例如 Ubuntu 系统下,该值为6,那么最多将重传 6 次(间隔是指数递增的, 1s、2s、4s、8s、16s、32s),6 次重试以后放弃重试,connect 调用返回 -1,调用超时。

数据传输阶段

重传定时器

  主要用于处理在发送数据包的时候没有收到 ACK 的情况。重传定时器的时间是动态计算的,取决于 RTT 和重传的次数。重传时间间隔也是指数级退避,直到达到 120s 为止,重传次数是15次(由操作系统的 /proc/sys/net/ipv4/tcp_retries2 决定),总时间将近 15 分钟。

延迟 ACK 定时器

  在 TCP 收到数据包以后在没有数据包要回复时,不马上回复 ACK。这时开启一个定时器,等待一段时间看是否有数据需要回复。如果期间有数据要回复,则在回复的数据中捎带 ACK,如果时间到了也没有数据要发送,则也发送 ACK。

keep-alive 定时器

  TCP 的设计中,如果双方都没有关闭连接,同时连接的空闲时间超过 2 小时,就会发送一个探测报文。如果对方有回复则表示连接还活着,对方还在,如果经过几次探测对方都没有回复则表示连接已失效,客户端会丢弃这个连接。keep-alive 定时器就是用于定时探测是否存活。

Persist 定时器

  专门用于零窗口探测。TCP 利用滑动窗口来实现流量控制,当接收端 B 接收窗口为 0 时,发送端 A 此时不能再发送数据,发送端此时开启 Persist 定时器,超时后发送一个特殊的报文给接收端看对方窗口是否已经恢复,这个特殊的报文只有一个字节。

挥手阶段

FIN_WAIT_2 定时器

  在挥手阶段,用 FIN_WAIT_2 定时器来防止被动关闭连接的一方一直不发送 FIN 包,导致关闭连接的一方一直处于等待状态。这个值由/proc/sys/net/ipv4/tcp_fin_timeout 决定,Ubuntu 系统中默认为 60 ms。

TIME_WAIT 定时器

  主动关闭连接的一方在接收到被动关闭连接的一方发送的 FIN 包,并发送 ACK后,需等待 2MSL 的时间才能关闭连接。这主要是为了可靠的实现 TCP 全双工的连接终止(处理最后 ACK 丢失的情况),避免当前关闭连接与后续连接混淆(让旧连接的包在网络中消逝)。因为在 TIME_WAIT 持续 2 个 MSL 的时间后,端口号才可以被安全的重用。

坚持原创技术分享,您的支持将鼓励我继续创作!