客户反馈系统中存在大量TIME_WAIT状态的TCP连接,导致新连接无法建立。
参考 ”TCP/IP 详解 卷 1 :协议 ” ,根据 TCP 规范,主动关闭的一方最后会进入 TIME_WAIT 状态,此状态的持续时间为2MSL。
说明:
Maximum Segment Lifetime,即一个数据帧在网络中生存的最长时间。
这个设计的主要目的是两点:
据上述,可以看到 TIME_WAIT 状态是有助于连接可靠性的(避免新连接收到旧连接的旧数据包)。
这种 2MSL 等待的一个附带后果是这个 TCP 连接在 2MSL 等待期间,定义这个连接的 socket 四元组 ( 客户的 IP 地址和端口号,服务器的 IP 地址和端口号 ) 不能再被使用。这个 四元组只能在 2MSL 结束后才能再被使用。
在 AIX 上, TIME_WAIT( 即 2MSL) 默认的时长是 15 秒钟,参考 no 命令的 tcp_timewait 选项:
root:[/] no -h tcp_timewait
Help for tunable tcp_timewait:
Purpose:
The tcp_timewait option is used to configure how long connections are kept in the timewait state.
Values:
Default: 1
Range: 1 - 5
Type: Dynamic
Unit: 15_second
Tuning:
It is given in 15 second intervals. Increasing this value will degrade performance of Web servers or applications that open and close a lot of TCP connections.
int ret, optval=1;
fd_ = socket(AF_INET, SOCK_STREAM, 0);
if(fd_ < 0)
{
printf("open failed\\n");
return -1;
}
if (setsockopt(fd_, SOL_SOCKET, SO_REUSEADDR,
(const void *)&optval , sizeof(int)) < 0)
return -1;
ret = bind(fd_, (SA *) &addr.addrin_, sizeof(addr.addrin_));
可以考虑扩大客户端的通配端口范围,例如:
# no -p -o tcp_ephemeral_low=9000 -o tcp_ephemeral_high=65500
# no -p -o udp_ephemeral_low=9000 -o udp_ephemeral_high=65500
在 AIX 上, Server 端主动关闭 Socket 连接时,在 TIME_WAIT 期间允许一种例外情况:
即与处于 TIME_WAIT 状态的 socket 四元组( 客户的 IP 地址和端口号,服务器的 IP 地址和端口号 ) 重复的新连接请求,如果到达的 SYN 的初始序列号 (ISN) " 大于 " 前一化身 ( 即处于 TIME_WAIT 状态的化身 ) 的结束序列号,则允许该重复连接请求, TCP 三次握手可以正常建立连接。
注意TCP序列号是 32 位的无符号整数, " 大于 " 的定义是:
#define SEQ_GT(a,b) ((int)((a)-(b)) > 0)
参考:
TCP/IP illustrated Volume1 Protocol:
18.6 TCP State Transition Diagram
TCP/IP illustrated Volume2 Implementation:
chapter 28-28
chapter 28-17
RFC 1122 规范对操作系统 TIME_WAIT 状态实现的要求 :
TCP REQUIREMENT SUMMARY
...
Send RST to indicate data lost SHOULD (应当实现)
In TIME-WAIT state for 2xMSL seconds MUST( 必须实现 )
Accept SYN from TIME-WAIT state MAY (可能实现)
Read more: http://www.faqs.org/rfcs/rfc1122.html
如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!
赞0
添加新评论0 条评论