目录
背景及现象
服务器:公网服务器
客户端:外网手游客户端
玩家侧现象:大批处于同一局域网内的内侧玩家连接服务器超时,但是切换成 4G 之后连接顺畅。
服务端现象:netstat -s"
显示 “passive connections rejected because of time stamp” 数量增长快速,关闭 tcp_tw_recycle
或 tcp_timestamps
恢复正常,玩家侧现象消失。
问题原因
tcp_tw_recycle
依赖于 tcp_timestamps
, 前者默认关闭,后者默认开启。如果二者都开启,当服务器收到 FIN 包时,这个 FIN 包中的时间戳值会按 IP 缓存起来(缓存 TCP_PAWS_MSL
, 即 60s),缓存时间内,当同一 IP 的 SYN 包时间戳小于该值,则直接丢弃。代码分析如下:
/* VJ's idea. We save last timestamp seen
* from the destination in peer table, when entering
* state TIME-WAIT, and check against it before
* accepting new connection request.
*
* If "isn" is not zero, this request hit alive
* timewait bucket, so that all the necessary checks
* are made in the function processing timewait state.
*/
if (tmp_opt.saw_tstamp &&
tcp_death_row.sysctl_tw_recycle &&
(dst = inet_csk_route_req(sk, req)) != NULL &&
(peer = rt_get_peer((struct rtable *)dst)) != NULL &&
peer->v4daddr == saddr) {
if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL &&
(s32)(peer->tcp_ts - req->ts_recent) >
TCP_PAWS_WINDOW) {
NET_INC_STATS_BH(sock_