tcp 三次握手和四次断连深入分析:连接状态和socket API的关系

时间:2022-02-27 06:07:48

说到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抓包例如以下:

tcp 三次握手和四次断连深入分析:连接状态和socket API的关系


抓包结果显示:server端直接回复了RST包

此时使用netstat或者ss命令去查看,不管是client还是server,都查不到连接


第2种情况:client调用connect,server调用了socket + bind + listen

tcpdump抓包例如以下:

tcp 三次握手和四次断连深入分析:连接状态和socket API的关系


抓包结果显示:三次握手完毕

使用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抓包例如以下:

tcp 三次握手和四次断连深入分析:连接状态和socket API的关系

抓包结果显示:三次握手完毕,并且两方都能够发送和接受数据了

使用ss工具去查看。client和server都显示ESTAB

[[email protected] ~]$ ss -t -n | grep 50000 ESTAB 0 0 10.1.73.45:41363 10.1.73.76:50000
【连接过程总结】

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抓包例如以下:

tcp 三次握手和四次断连深入分析:连接状态和socket API的关系


抓包结果显示:client发送了fin包,server端应答了ack包


使用ss工具去查看。client显示FIN_WAIT_2状态:

[[email protected] ~]$ ss -t -n | grep "10.1.73.76:50000" FIN-WAIT-2 0 0 10.1.73.45:47630 10.1.73.76:50000
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抓包例如以下: