51608699434_.pic.jpg
tips:

  1. 从LISTEN到SYN_SENT的状态转换在TCP协议中是合法的,但却不被伯克利Socket所支持,因此比较少见
  2. 从SYN_RCVD返回到LISTEN的状态转换只在SYN_RCVD状态是由LISTEN状态转换而来的情况下才是正确的。

TIME_WAIT状态

在该状态中,TCP将会等待两倍于最大段生存期(Maximum Segment Lifetime)的时间。

最大段生存期表示任何报文段在被丢弃前在网络中被允许存在的最长时间。

当TCP执行一个主动关闭并发送最终的ACK时,连接必须处于TIME_WAIT状态并持续两倍于最大生存期的时间。
这样能够让TCP重新发送最终的ACK以避免出现丢失的情况。

重新发送ACK不是因为TCP重传了ACK,而是因为另一方重传了FIN。 事实上,TCP总是重传FIN,直到它收到一个最终的ACK。

当TCP处于TIME_WAIT状态时,通信双方将该连接(即定义该连接的ip和端口)定义为不可用。
只有当2MSL等待结束时,或一条新连接使用的初始序列号超过了连接之前的实例所使用的最高序列号时,或者允许使用时间戳选项来区分之前连接实例的报文段以避免混淆时,这条连接才能被再次使用。

不过,许多实现和API都提供了绕开这一约束的方法。


FIN_WAIT_2状态

主动关闭连接的一方,在发送FIN并接收到ACK之后,就会进入FIN_WAIT_2状态。
这是一个无限等待的状态,只有接收到对端发送过来的FIN并发送ACK之后,才会进入TIME_WAIT状态。

在这一状态下,依然可以接收到对端发送过来的数据,但是自己不能发送数据了。

如果在这一状态下执行的是一个完全关闭操作,不期望接收数据,那么就会设置一个计时器,当计时器超时时连接是空闲的,那么TCP连接会进入CLOSED状态。

在linux系统中可以调整变量net.ipv4.tcp_fin_timeout的值来控制计时器的秒数。默认是60秒。