TIME_WAIT状态下对接收到的数据包如何处理 1、保证TCP连接关闭的可靠性。如果最终发送的ACK丢失,被动关闭的一端会重传最终的FIN包,如果执行主动关闭的一端没有维护这个连接的状态信息,会发送RST包响应,导致连接不正常关闭。 2、允许老的重复分组在网络中消逝。假设在一个连接关闭后,发起建立连接的一端(客户端)立即重用原来的端口、IP地址和服务端建立新的连接。老的连接上的分组可能在新的连接建立后到达服务端,TCP必须防止来自某个连接的老的重复分组在连接终止后再现,从而被误解为同一个连接的化身。要实现这种功能,TCP不能给处于TIME_WAIT状态的连接启动新的连接。TIME_WAIT的持续时间是2MSL,保证在建立新的连接之前老的重复分组在网络中消逝。这个规则有一个例外:论文网 如果到达的SYN的序列号大于前一个连接的结束序列号,源自Berkeley的实现将给当前处于TIME_WAIT状态的连接启动新的化身。 最初在看《Unix网络编程》 的时候看到这个状态,但是在项目中发现对这个状态的理解有误,特别是第二个理由。原本认为在TIME_WAIT状态下肯定不会再使用相同的五元组(协议类型,源目的IP、源目的端口号)建立一个新的连接,看书还是不认真啊!为了加深理解,决定结合内核代码,好好来看下内核在TIME_WAIT状态下的处理。其实TIME_WAIT存在的第二个原因的解释更多的是从被动关闭一方的角度来说明的。如果是执行主动关闭的是客户端,客户端户进入TIME_WAIT状态,假设客户端重用端口号来和服务器建立连接,内核会不会允许客户端来建立连接?内核如何来处理这种情况?书本中不会对这些点讲的那么详细,要从内核源码中来找答案。 我们先来看服务器段进入TIME_WAIT后内核的处理,即服务器主动关闭连接。TCP层的接收函数是tcp_v4_rcv(),和TIME_WAIT状态相关的主要代码如下所示:
[cpp] view plaincopyprint? 01.int tcp_v4_rcv(struct sk_buff *skb) 02.{ 03. ...... 04. 05. sk = __inet_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest); 06. if (!sk) 07. goto no_tcp_socket; 08.process: 09. if (sk->sk_state == TCP_TIME_WAIT) 10. goto do_time_wait; 11. ...... 12. 13.discard_it: 14. /* Discard frame. */ 15. kfree_skb(skb); 16. return 0; 17. ...... 18.do_time_wait: 19. ...... 20. 21. switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) { 22. case TCP_TW_SYN: { 23. struct sock *sk2 = inet_lookup_listener(dev_net(skb->dev), 24. &tcp_hashinfo, 25. iph->daddr, th->dest, 26. inet_iif(skb)); 27. if (sk2) { 28. inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row); 29. inet_tws [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] ... 下一页 >>
|