Administrator
Published on 2021-07-17 / 263 Visits
0

TCP中的三次握手和四次挥手

图解

三次握手:
image.png
四次挥手:
image.png

抓包时对应的数据:
(应用层在http请求时存在,本章例子用的是TCP所以不存在。)
image.png

TCP包首部:
image.png
image.png

网络传输过程:
image.png

OSI模型:
image.png
image.png

Wireshark抓包工具进行分析

基本分析

192.168.1.155开启TCP服务器,监听端口5000。
192.168.1.60作为TCP客户端,去连接155的服务器。

如图,当客户端连接服务器,可以抓包的三个TCP包,对应了三次握手:
image.png

如图,当客户端断开连接服务器,可以抓包的四个TCP包,对应了四次挥手:
image.png

通过OSI模型可知道,TCP处于传输层,所以我们抓包主要看Transmission Control Protocol里面的数据,此处挑选三次握手的第一包数据来看,是完全符合TCP首部的定义的:
image.png

三次握手分析

第一包,SYN为1,seq为1340667231:
image.png
第二包,SYN为1,ACK为1,ack为1340667232,seq为1529813301:
image.png
第三包,ACK为1,ack为1529813302:
image.png
通过分析,可知符合图解中的图片步骤。

四次挥手分析

与三次握手的分析过程一致,此处就不再分析了。

四次挥手,CLOSE_WAIT,TIME_WAIT

1.四次挥手的发起可在客户端或者服务端,从上面图示可以知道,CLOSE_WAIT状态出现在被动关闭的那方,TIME_WAIT状态出现在主动关闭的那方。

2.如果出现大量CLOSE_WAIT,那可能就是被动关闭的那方没有正确关闭tcp,没有发送FIN=1,ACK=1,致使CLOSE_WAIT状态无法进入下一个状态。

没有正确关闭,可能是服务器没有相关资源进行处理,比如此时CPU100%等情况。
close_wait状态出现的原因是被动关闭方未关闭socket造成。

3.http下,一般来说,断开连接是由客户端来断开,在这种情况下,如果大量TIME_WAIT出现在服务端,那就是http客户端的http请求头中,connection 字段取值被设置为 close,此值代表着客户端发起的http(核心是tcp)服务器处理完毕后,由服务器主动关闭tcp。
而TIME_WAIT状态,通过上面的图示,进入closed状态需要等待2MSL,所以当有大量客户端时进行访问时,我们就会看到大量TIME_WAIT状态了。
等待2
MSL时间,如果有大量客户端,这将会占用过多的服务器资源,所以server端应尽量减少主动关闭连接。

在 HTTP/1.1 协议中,默认开启 keep-alive。HTTP 请求的头部,connection 一般设置为 keep-alive,代表着http请求即使处理完毕,还会保持存活一段时间(此时服务器上看,存在ESTABLISHED状态的tcp连接)。现在的浏览器,一般也都这么进行。
换种正式的说法,就是服务端在返回 response 后不关闭 TCP 连接,同样的,在接收完响应报文后,客户端也不关闭连接,进行下一个 HTTP 请求时会重用该连接。主要作用是 TCP连接复用,避免建立过多的TCP连接。
在微服务架构中,通常微服务的使用方和提供方会长期有交流,此时最好开启 keep-alive。
具体的连接复用时间的长短,通常是由web服务器控制的,在HTTP协议中,Keep-Alive属性保持连接的时间长短是由服务端决定的,通常配置都是在几十秒左右,例如,在tomcat中,我们可以server.xml中配置以下属性:maxKeepAliveRequests:一个连接上,最多可以发起多少次请求,默认100,超过这个次数后会关闭;keepAliveTimeout:底层socket连接最多保持多长时间,默认60秒,超过这个时间连接会被关闭。
此外,客户端可以自定义存活时间,存活时间受http头的Keep-Alive参数限制,比如Keep-Alive:timeout=5,max=100,timeout代表过期时间5秒,max是最多复用一百次请求,就强制断掉连接。

http/1.0短连接connection默认为close,http/1.1长连接connection默认为keep-alive

在OkHttpClient中,默认时 HTTP头字段 Connection 设置值为keep-alive,这样会导致服务端断开连接时,客户端不能及时的断开连接,从而出现大量的CLOSE_WAIT。

注意

在测试过程中,有些TCP工具,在断开时只抓到了两个TCP包。

TCP KeepAlive机制

概念

KeepAlive机制是tcp层实现的心跳机制,与通常的应用层实现心跳机制差不多,用来检测对方tcp连接是否正常,对方主机是否崩溃。
KeepAlive机制由tcp服务端程序自己决定开不开启,探测tcp连接。
当对方无报文回应时,KeepAlive机制就关闭对应的tcp,避免浪费服务器的资源。

参考

TCP keepalive的详解(解惑)
https://blog.csdn.net/lanyang123456/article/details/90578453
TCP保活机制(KeepAlive)
https://blog.csdn.net/ComplexMaze/article/details/124201088

参考

前端网络与安全之connection为keep-alive是什么意思?
https://blog.csdn.net/leelxp/article/details/108096660
HTTP协议的Keep-Alive 模式
https://www.jianshu.com/p/49551bda6619
OkHttpClient调用出现大量CLOSE_WAIT
https://www.cnblogs.com/voipman/p/10195164.html
为什么TCP4次挥手时等待为2MSL?
https://www.zhihu.com/question/67013338
终于搞懂了服务器为啥产生大量的TIME_WAIT!
https://zhuanlan.zhihu.com/p/415307243
httpclient使用不当产生大量CLOSE_WAIT的解决过程
https://blog.csdn.net/truelove12358/article/details/103122167
TIME_WAIT和CLOSE_WAIT状态区别
https://www.jianshu.com/p/f6a563f3526c
TCP keepalive 和 http keep-alive
https://segmentfault.com/a/1190000012894416#:~:text=Http keep-alive 在 HTTP 1.0,时期,每个 TCP 连接只会被一个 HTTP Transaction(请求加响应)使用,请求时建立,请求完成释放连接。
Http——Keep-Alive机制
https://www.cnblogs.com/caoweixiong/p/14720254.html
聊聊 TCP 中的 KeepAlive 机制
https://zhuanlan.zhihu.com/p/28894266