linux网络编程TCP_DEFER_ACCEPT

来源:互联网 发布:地球联合理事会 知乎 编辑:程序博客网 时间:2024/05/18 00:59

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后,内核不等待最后一个ACK包,而且在第一个真正有数据的包到达后才初始化侦听过程,可以减少一些上下文切换,三次握手后,如果没有数据到来,服务器socket处于SYN_RECV状态,这个时候就依赖于net.ipv4.tcp_synack_retries参数控制了,当达到重传后,过指定的时间关闭socket

 

看测试程序

服务器环境:Linux version 2.6 + gcc,ip:192.168.30.202

客户端环境:win32 + vs2010,ip:192.168.30.12

 

没有设置TCP_DEFER_ACCEPT,三次握手的抓包:

 

[root@localhost ~]# tcpdump tcp port 10000

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes

16:30:59.486716 IP 192.168.30.12.4326 > 192.168.30.202.ndmp: S 1992149464:1992149464(0) win 65535 <mss 1460,nop,nop,sackOK>

16:30:59.490951 IP 192.168.30.202.ndmp > 192.168.30.12.4326: S 524361898:524361898(0) ack 1992149465 win 5840 <mss 1460,nop,nop,sackOK>

16:30:59.491059 IP 192.168.30.12.4326 > 192.168.30.202.ndmp: . ack 1 win 65535

 

设置TCP_DEFER_ACCEPT,通过命令“sysctl -w net.ipv4.tcp_synack_retries=1”设置重传后,抓包如下:

 

[root@localhost ~]# tcpdump tcp port 10000

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes

16:35:12.764157 IP 192.168.30.12.4548 > 192.168.30.202.ndmp: S 1431219651:1431219651(0) win 65535 <mss 1460,nop,nop,sackOK>

16:35:12.767924 IP 192.168.30.202.ndmp > 192.168.30.12.4548: S 795485424:795485424(0) ack 1431219652 win 5840 <mss 1460,nop,nop,sackOK>

16:35:12.768044 IP 192.168.30.12.4548 > 192.168.30.202.ndmp: . ack 1 win 65535

16:35:15.726875 IP 192.168.30.202.ndmp > 192.168.30.12.4548: S 795485424:795485424(0) ack 1431219652 win 5840 <mss 1460,nop,nop,sackOK>

16:35:15.726980 IP 192.168.30.12.4548 > 192.168.30.202.ndmp: . ack 1 win 65535

 

设置TCP_DEFER_ACCEPT,通过命令“sysctl -w net.ipv4.tcp_synack_retries=3”设置重传后,抓包如下:

 

[root@localhost ~]# tcpdump tcp port 10000

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes

16:36:57.993105 IP 192.168.30.12.4648 > 192.168.30.202.ndmp: S 242062800:242062800(0) win 65535 <mss 1460,nop,nop,sackOK>

16:36:57.996526 IP 192.168.30.202.ndmp > 192.168.30.12.4648: S 917726329:917726329(0) ack 242062801 win 5840 <mss 1460,nop,nop,sackOK>

16:36:57.996567 IP 192.168.30.12.4648 > 192.168.30.202.ndmp: . ack 1 win 65535

16:37:02.140832 IP 192.168.30.202.ndmp > 192.168.30.12.4648: S 917726329:917726329(0) ack 242062801 win 5840 <mss 1460,nop,nop,sackOK>

16:37:02.141226 IP 192.168.30.12.4648 > 192.168.30.202.ndmp: . ack 1 win 65535

16:37:08.065966 IP 192.168.30.202.ndmp > 192.168.30.12.4648: S 917726329:917726329(0) ack 242062801 win 5840 <mss 1460,nop,nop,sackOK>

16:37:08.066190 IP 192.168.30.12.4648 > 192.168.30.202.ndmp: . ack 1 win 65535

16:37:19.915745 IP 192.168.30.202.ndmp > 192.168.30.12.4648: S 917726329:917726329(0) ack 242062801 win 5840 <mss 1460,nop,nop,sackOK>

16:37:19.915993 IP 192.168.30.12.4648 > 192.168.30.202.ndmp: . ack 1 win 65535

 

上面抓包结果可以看出结果,不过还有个问题没弄明白,当达到重传次数后,过指定的时间关闭socket,这个时间没有准确的计算出来

 

int val = 10;

if (setsockopt(sock_descriptor, IPPROTO_TCP, TCP_DEFER_ACCEPT, &val, sizeof(val))== -1)

{

perror("setsockopt");

exit(1);

}

 

val以秒为单位,val设置的时间越久,测试出这个等待关闭的时间就越久,具体没弄清楚是多少,或者是由其他什么控制的,杯具啊!!

 

 

 

 

 

 

 

 

 

 

原创粉丝点击