说到tcp协议,凡是略微看过的人都能顺口说出三次握手和四次断连。再牛逼的一点的就能够把每一个状态(SYNC_SENT、CLOSE_WAIT。
。。。
。。等)都能背出来,
而说道socket编程。基本上写过网络编程的人都会熟悉那几个标准的API:socket、connect、listen、accept。。。。
。。等
可是。我敢打赌非常少有人明确tcp状态和socket编程API之间的关系。不信? 看看例如以下几个问题你是否知道吧:
1)什么时候客户端才干够连接上server端, 是server端调用bind后还是listen后还是accept后 ?
2)什么情况下会出现FIN_WAIT_2状态
。
。
。。。。
。。。。
。。
。。。
。。
。。。。
本周打破砂锅问究竟的精神以及实事求是的精神,我用python脚本写了一些脚本測试这些情况。看完后你一定会大呼过瘾,对tcp的协议和socket编程的理解又更上层楼。
注:下面測试是在Linux(2.6.18)平台上用python(2.7)脚本測试。其他平台没有測试。有兴趣能够自己測试一下。
【连接过程測试和验证】
第1种情况:client调用connect,server仅仅是调用了socket + bind,,没有调用listen
tcpdump抓包例如以下:
抓包结果显示:server端直接回复了RST包
此时使用netstat或者ss命令去查看,不管是client还是server,都查不到连接
第2种情况:client调用connect,server调用了socket + bind + listen
tcpdump抓包例如以下:
抓包结果显示:三次握手完毕
使用ss工具去查看,client和server都显示ESTAB
[[email protected] ~]$ ss -t -n | grep 50000 ESTAB 0 0 10.1.73.45:55354 10.1.73.76:50000第3种情况:client调用connect + send,server调用了socket + bind + listen + accept + recv + send
tcpdump抓包例如以下:
抓包结果显示:三次握手完毕,并且两方都能够发送和接受数据了
使用ss工具去查看。client和server都显示ESTAB
【连接过程总结】
1)能够看到,仅仅有当server端listen之后,client端调用connect才干成功,否则就会返回RST响应拒绝连接
2)仅仅有当accept后,client和server才干调用recv和send等io操作
3)socket API调用错误不会导致client出现SYN_SENT状态,那么仅仅能是网络设备丢包(路由器、防火墙)才会导致SYNC_SENT状态
【断连过程測试和总结】
第1种情况:client调用close,但server没有调用close
tcpdump抓包例如以下:
抓包结果显示:client发送了fin包,server端应答了ack包
使用ss工具去查看。client显示FIN_WAIT_2状态:
server显示CLOSE-WAIT状态[[email protected]_test ~]$ ss -t -n | grep 50000 CLOSE-WAIT 1 0 10.1.73.76:50000 10.1.73.45:47630 并且有一个值得注意的现象是:client的连接过一段时间就没有了,而server的连接一直处于CLOSE_WAIT状态
原因在于Linux系统内核中有一个參数能够控制FIN_WAIT_2的时间:tcp_fin_timeout
第2种情况:client调用close。server调用close
tcpdump抓包例如以下: