标签:
现象:
以下为其他网站提供,和我遇到的情况一样。
就是服务器老是重复发送 SYN, ACK。
4414.229553 client -> server TCP 62464 > http [SYN] Seq=0 Win=65535 Len=0 MSS=1452 WS=3 TSV=116730231 TSER=0
4414.229633 server -> client TCP http > 62464 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=2406364374 TSER=116730231 WS=6
4414.263330 client -> server TCP 62464 > http [ACK] Seq=1 Ack=1 Win=524280 Len=0 TSV=116730231 TSER=2406364374
4418.812859 server -> client TCP http > 62464 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=2406365520 TSER=116730231 WS=6
4418.892176 client -> server TCP [TCP Dup ACK 778#1] 62464 > http [ACK] Seq=1 Ack=1 Win=524280 Len=0 TSV=116730278 TSER=2406365520
4424.812864 server -> client TCP http > 62464 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=2406367020 TSER=116730278 WS=6
4424.891240 client -> server TCP [TCP Dup ACK 778#2] 62464 > http [ACK] Seq=1 Ack=1 Win=524280 Len=0 TSV=116730337 TSER=2406367020
可能的问题:供参考
OK, I don‘t have a full answer, but I‘ve learned a lot since this issue first came up. I‘ll share my insights here.
telnet www.website.com 80
and not sending any data. It could still be a Linux peculiarity though, as the servers I tested may well all run Linux. This behaviour also happened without any iptables-rules loaded, so it‘s really kernel-related.iptables
connection-tracking doesn‘t seem to share this logic, so there the connection will remain in the ESTABLISHED
state until it times out. The default timeout of this is 5 days (!). I‘m planning to reduce this to something more sensible such as a few hours.nc -l ###
and connected to that. So it might be a certain TCP option Apache sets on its listening socket. Or it might be something entirely unique to Apache. Most other daemons announce themselves immediately after connection, so they are no valid test cases for this. The connection needs to do a 3-way handshake and then immediately fall idle.以上为网上的一些分析,我结合自己的情况。基本可以肯定我的路由器有问题。因为我在配置好端口映射之后,外网可以访问路由器的远程web 管理页面,而空闲一段时间或过一晚上,第二天发现外网的远程web 管理页面无法连接,其他的映射端口也无法连接。内网抓包发现和以上描述的现象。
===============================================================================
咳,刚写完就找到最终答案了:
监听socket 使用了TCP_DEFER_ACCEPT选项。
————————————————————————————————————————————————————————————————
1. 设置TCP_DEFER_ACCEPT
int val = 10; // time_out
if (setsockopt(sock_descriptor, IPPROTO_TCP, TCP_DEFER_ACCEPT, &val, sizeof(val))== -1)
{
perror("setsockopt");
exit(1);
}
2. TCP_DEFER_ACCEPT的效果
正常的tcp三次握手过程:
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认; 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态; 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手
设置TCP_DEFER_ACCEPT后
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认; 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态; 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,连接并不进入ESTABLISHED状态,而是在第一个真正有数据的包到达后才进入ESTABLISHED,完成连接的建立。
TCP_DEFER_ACCEPT的超时
在第三次握手时候,如果客户段迟迟不发送数据,服务器 连接将一直处于syn_recv状态。此时内核会重传 syn_ack ,重传的次数可以通过 sysctl -w net.ipv4.tcp_synack_retries=3来设置,如果3次重传后,客户端依然没有数据,在等待 设置TCP_DEFER_ACCEPT时候指定的超时时间后(这个时间单位为s,可是测试看来并不精准的执行),系统将回收连接,并不对客户端发出rst或者fin包。
服务器重复发送SYN ACK 和 TCP_DEFER_ACCEPT设置
标签:
原文地址:http://www.cnblogs.com/littleKing163/p/TCP.html