time_wait,不要乱用tcp_tw_recycle和net.ipv4.tcp_tw_reuse

转载链接:https://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux#fn-rfc1337

服务器端time_wait满了后,客户端相同的port为什么还能正常被请求:

        When a connection is closed actively, it MUST linger in
            TIME-WAIT state for a time 2xMSL (Maximum Segment Lifetime).
            However, it MAY accept a new SYN from the remote TCP to
            reopen the connection directly from TIME-WAIT state, if it:

            (1)  assigns its initial sequence number for the new
                 connection to be larger than the largest sequence
                 number it used on the previous connection incarnation,
                 and

            (2)  returns to TIME-WAIT state if the SYN turns out to be
                 an old duplicate.

https://superuser.com/questions/1179009/ephemeral-port-collision

https://tools.ietf.org/html/rfc1122

另isn的生成规则:

When new connections are created,
  an initial sequence number (ISN) generator is employed which selects a
  new 32 bit ISN.  The generator is bound to a (possibly fictitious) 32
  bit clock whose low order bit is incremented roughly every 4
  microseconds.  Thus, the ISN cycles approximately every 4.55 hours.
  Since we assume that segments will stay in the network no more than
  the Maximum Segment Lifetime (MSL) and that the MSL is less than 4.55
  hours we can reasonably assume that ISN's will be unique.
https://tools.ietf.org/html/rfc793


其他博客:http://blog.csdn.net/justlinux2010/article/details/8725479

如果是RST包的话,并且系统配置sysctl_tcp_rfc1337(默认情况下为0,参见/proc/sys/net/ipv4/tcp_rfc1337)的值为0,这时会立即释放time_wait传输控制块,丢掉接收的RST包。
  如果是ACK包,则会启动TIME_WAIT定时器后丢掉接收到的ACK包。
  接下来是对SYN包的处理。前面提到了,如果在TIME_WAIT状态下接收到序列号比上一个连接的结束序列号大的SYN包,可以接受,并建立新的连接,下面这段代码就是来处理这样的情况:

[cpp]  view plain  copy
  1. if (th->syn && !th->rst && !th->ack && !paws_reject &&  
  2.     (after(TCP_SKB_CB(skb)->seq, tcptw->tw_rcv_nxt) ||  
  3.      (tmp_opt.saw_tstamp &&  
  4.       (s32)(tcptw->tw_ts_recent - tmp_opt.rcv_tsval) < 0))) {  
  5.     u32 isn = tcptw->tw_snd_nxt + 65535 + 2;  
  6.     if (isn == 0)  
  7.         isn++;  
  8.     TCP_SKB_CB(skb)->when = isn;  
  9.     return TCP_TW_SYN;  
  10. }  

验证:

可通过raw socket,返送syn包,

经测试:

1.server time_wait,假设接受到的最后ack:x,

2.client,相同ip和端口,发送syn包,如果isn小于x,那么会发送的是ack:x,而不会是ack+syn,故不会接受连接,还是time_wait

3.client,相同ip和端口,发送syn包,如果isn大于x,那么会发送ack:isn+1和syn,因此会直接进行握手连接,因此可以快速使用该4元组的tcp


raw socket demo:http://blog.csdn.net/lizhia1221/article/details/51946592

发布了140 篇原创文章 · 获赞 28 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/qq_16097611/article/details/79080687