TCP建立连接–三次握手

其实TCP建立连接的三次握手网上有很多的啦,下面给出我的理解:

img

状态解释

CLOSED:虚拟出来的状态,实际不存在,你在netstat -ant | grep 端口的时候是找不到的;

LISTEN:表示Server大门已开,随时准备有Client前来连线;

SYN_SENT:只在Client端出现,表示Client发送过SYN了,正在焦急地等待Server的ACK;

SYN_RCVD:只在Server端出现,表示Server收到Client的SYN了,并且已经发给Client自己的ACK和SYN了,正在焦急地等待Client的ACK;

ESTABLISHED:在Client端出现表示Client把自己的ACK(第3次握手)发出去了,Client已经就绪;在Server端出现表示Server已经收到Client的ACK(第3次握手)了,Server已经就绪;

注:只有在Client和Server同时为ESTABLISHED时,即同时就绪时才可以进行数据传输。

Client端口状态转换

应用层调用connect,发送SYN到对端,等待对端的ACK和SYN;

等待对端的ACK和SYN到来,接收到ACK和SYN后,发出自己的ACK,状态进入ESTABLISHED;

等待对端的ACK和SYN期间,端口状态一直为SYN_SENT,超时后进入CLOSED;

Server端口状态转换

应用层启动侦听,端口进入LISTEN状态;

接收到Client发来的SYN,发送自己的ACK和SYN,进入SYN_RCVD状态,等待Client的ACK;

等待Client的ACK到来,接收到ACK后,进入ESTABLISHED;等待超时,进入CLOSED;

TCP断开连接–四次挥手

TCP通讯双方,不管是Client还是Server,都可以主动断开连接,所以下面我们只以主动方和被动方为标注。(实际情况一般由客户端主动关闭,服务端关闭的也有,看到服务端端口状态为TIME_WAIT时不要奇怪)。

img

状态解释

FIN_WAIT_1:仅出现在主动方,表示主动方想要断开连接,已经关闭了写通道,并向对端发送了FIN,等待对方的ACK到来;

CLOSE_WAIT:仅出现在被动方,表示被动方收到FIN后,已经回复ACK,正在等自己的应用层调用close方法关闭写通道,在CLOSE_WAIT状态下,自己只能发送数据,但不能接收数据;

FIN_WAIT_2:仅出现在主动方,表示主动方已收到对端的ACK,等待对端的FIN,此时无法再发送数据,但是可以接收数据;

LAST_ACK:仅出现在被动方,表示被动方缓冲区数据已经发送完毕,并且已经发送FIN到对端,等待对端的ACK;如果应用层写的比较垃圾,没有调用close关闭socket,则会一直停留在CLOSE_WAIT;

TIME_WAIT:仅出现在主动方,表示主动方已经发出ACK了,本次通讯完事了,双方都不能再读写了,但是主动方不确定对方能不能收到最后一个ACK,为了保证这个端口释放后,不被后来的连接马上使用被当成是新连接,通俗地讲,为了不乱套,这个状态会一直等待,等多久呢, 等2×MSL(Maximum Segment Lifetime)个时间,这个MSL是操作系统配置的,有默认参数,可以改。

主动方端口状态转换

应用层调用close方法发起关闭连接;

发送FIN到对端,关闭写通道,端口进入FIN_WAIT_1状态;

等待对端的确认ACK到来,接收到ACK后进入FIN_WAIT_2状态;如果在超时时间内没有收到ACK则直接进入CLOSED状态;

如果在FIN_WAIT_1状态时收到了对端的FIN,则进入CLOSING状态

如果在FIN_WAIT_2状态时收到了对端的FIN,则进入TIME_WAIT状态;如果在超时时间内没有收这个FIN则直接进入CLOSED状态;

在TIME_WAIT状态等待2个MSL(报文最长存活周期)后进入CLOSED状态;

被动方端口状态转换

收到对端的FIN后,关闭读通道,自己进入CLOSE_WAIT状态;

在CLOSE_WAIT状态等待应用层调用close方法关闭socket连接;

如果在超时时间内没调用close,则直接进入CLOSED状态;

如果在超时时间内调用了close,则向对端发送FIN,自己进入LAST_ACK状态,等待对端的ACK;

等待对端的ACK,如果在超时时间内收到了ACK则直接进入CLOSED状态,否则超时后进入CLOSED状态;

调优

上边已经提到了,服务端有时也会主动关闭连接,应该是为了避免有些不地道的Client在撩完以后不关闭socket连接,一直占用服务器资源,所以有些服务器也会无情地主动关闭连接,为了自己不被干倒。

在高并发场景下,服务器主动关闭连接的情况,在服务端会出现大量的TIME_WAIT状态的端口,会占用操作系统文件句柄资源,导致新的连接可能无法建立,影响高并发性能,而关于TCP参数的调优中,有一大堆,但有一些参数调优对业务是有风险的,所以这里只给出一个相对比较安全的推荐调优,源自《码出高效 阿里巴巴Java开发手册 终极版 (1.3.0)》。

在Linux服务器上,/etc/sysctl.conf文件中修改time_wait缺省值(默认240秒):

net.ipv4.tcp_fin_timeout = 30

原文链接:https://blog.csdn.net/miss_ruochen/article/details/80782228

本博客所有内容采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可

转载文章请注明:TCP连接过程和状态变化 - https://yangxx.net/?p=3990

分类: linux

young

记住该记住的,忘记该忘记的,改变能改变的,接受不能改变的!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

我不是机器人*