TCP在以下情况下可能会进入TIME_WAIT状态:
(1)在TCP_FIN_WAIT2状态时调用close系统调用时;
(2)TCP_FIN_WAIT2收到对端的FIN时(一定会进入TIME_WAIT状态);
(3)成为orphan sock并且在TCP_FIN_WAIT1状态下收到ACK时;
(4)TCP_CLOSING状态下收到ACK时(一定会进入TIME_WAIT状态);
(5)FIN_WAIT2定时器超时时。
处于TIME_WAIT状态的TCP连接会保持2MSL(Maximum Segment Lifetime)时间,即2倍的最大生存时间。在这段时间内,相同源|目的IP和源|目的端口的TCP连接无法建立。这样做的目的主要有两个:1)禁止旧连接的报文危害新连接;2)收到对端重传的FIN时回应ACK,使对端尽快释放连接资源。
进入TIME_WAIT状态的函数为tcp_time_wait:
266 void tcp_time_wait(struct sock *sk, int state, int timeo)
267 {
268 struct inet_timewait_sock *tw = NULL;
269 const struct inet_connection_sock *icsk = inet_csk(sk);
270 const struct tcp_sock *tp = tcp_sk(sk);
271 bool recycle_ok = false;
272
273 if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp) //设置了快速回收tw sock并且开启了时间戳
274 recycle_ok = tcp_remember_stamp(sk);//记录时间戳信息到对端IP地址对应的信息管理块中;如果找到信息管理块,则recycle_ok为1
275
276 if (tcp_death_row.tw_count < tcp_death_row.sysctl_max_tw_buckets) //正在使用的tw sock的数量未超过限制
277 tw = inet_twsk_alloc(sk, state); //申请tw sock
278
279 if (tw != NULL) {
280 struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
281 const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1); //rto = 3.5 * icsk->icsk_rto
282 struct inet_sock *inet = inet_sk(sk);
283 //将socket中的信息记录到tw sock中
284 tw->tw_transparent = inet->transparent;
285 tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale;
286 tcptw->tw_rcv_nxt = tp->rcv_nxt;
287 tcptw->tw_snd_nxt = tp->snd_nxt;
288 tcptw->tw_rcv_wnd = tcp_receive_window(t