tcp连接的断开

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了tcp连接的断开相关的知识,希望对你有一定的参考价值。

参考技术A TCP的断开就是经过四次挥手:

这是正常的情况,客户端主动tcp连接断开的过程。客户端先是发送一个FIN为一的报文,然后进入FIN_WAIT_1的状态。
服务器收到FIN报文后,发送一个ACK报文,然后进入CLOSED_WAIT状态。
客户端收到服务器的ACK报文进入FIN_WAIT_2状态。
等到服务器觉得他数据处理好了,可以关闭的时候,会发送一个FIN报文,然后进入LAST_ACK。等待最后一个应答。
让客户端收到服务器FIN报文,就进入TIME_WAIT状态了,随后发送最后一个ACK报文,然后close。
客户端再等待2msl后也自己主动关闭。而只有主动关闭的情况下,才会有TIME_WAIT。

那么为什么四次挥手需要四次呢?
三次握手其实就是在第二次把ACK和SYN两个报文合并成一个发,但是断开的过程可能还有一方需要处理下数据,需要延长点时间,等处理好再发FIN,所以就比三次握手多了一次。

这里还有一个问题,为什么需要TIME_WAIT,然后到close需要2msl的时间呢?

先说下什么是MSL,也就是报文的最长生存时间,超过这个时间的报文就要被丢弃掉。tcp是基于ip的,ip上有个生存时间TTL,是ip报文可以经过的最大路由数量,每经过一个路由就减1,减到0,ip报文就丢弃掉,然后通过ICMP通知源主机,我们的ping也算是经过这个。当然msl和ttl还是有区别的,msl是时间,ttl是路由数量,msl也是大于等于ttl的。在linux中,2msl默认是60秒。

前文也说了,只有主动发起断开连接的进程才会有time wait状态。time wait+2msl有两个原因:
1.防止旧连接的数据包

像这个seq 301的包,如果因为网络的原因被延迟了,而没有time wait或者很短,那么连接断开后,又建立新的连接,这个时候这个包到了,可能就导致数据紊乱了。而2msl可以保证两个方向的包在断开前丢弃掉。

2.保证正确的断开连接
2msl的时间也是保证第四个报文的ack可以被被动关闭方接收到。

如图,假设time wait比较短或者没有,当最后的ack报文丢失的时候。客户端已经close了,而服务器一直处于last ack的状态。这样连接就不能正常断开了。而如果有time wait +2msl这个情况就可以避免。假设服务器没有收到最后一个ack报文,服务器会重发FIN等待客户端的ack。
这样就可以保证不会出现一端断开,另外一端没有断开的情况了。

有时候我们在服务器上会看到很多time wait。time wait一般就是服务器主动发起的断开请求才会产生的状态。所以time wait过多,第一个是系统资源会大量消耗,还有是端口如果占的太多,会导致没办法创建新连接。这个时候可以把linux的net.ipv4.tcp_tw_reuse开启,置为1,可以复用time wait超过1秒的连接。

这边再说说tcp的保活机制。也就是怎么长期维持客户端和服务端的连接。
在一个时间段内,如果没有连接等相关活动,tcp的保活机制会定期发探测报文,如果连续几个探测报文就没有回应,就将错误信息报告给系统,系统通知上层应用。

在 Linux 内核可以有对应的参数可以设置保活时间、保活探测的次数、保活探测的时间间隔,以下都为
默认值:
tcp_keepalive_time=7200:表示保活时间是 7200 秒(2⼩时),也就 2 小时内如果没有任何连接
相关的活动,则会启动保活机制
tcp_keepalive_intvl=75:表示每次检测间隔 75 秒;
tcp_keepalive_probes=9:表示检测 9 次无响应,认为对⽅方是不不可达的,从⽽而中断本次的连接。
也就是说在 Linux 系统中,最少需要经过 2 小时 11 分 15 秒才可以发现一个「死亡」连接。
当然这个时间也可以自己配置。

swoole tcp突然断开连接

参考技术A

情景:当你接入一些物联通讯一些设备时,肯定需要接触到TCP连接,但有时会出现“ 开始连接正常,中途断开的连接 ”,具体原因无从下手。

原因:开始连接正常不做多说,断开肯定是客户端无法和服务端通讯导致的
1.tcp并发连接数(swoole->set中max_con默认值:ulimit -n,原因是某些系统设置了 ulimit -n 为 100万,也可以设置reactor_num,worker_num,max_request等参数来处理自己的业务,我这里没有遇到并发的情况,请大家谅解)
2.超出连接最大空闲(心跳时间)
上面两种原因是在下理解的,如果还有其他原因希望大家可以评论告诉我,其实我也是个小白。

第一种原因就不说了,需要根据业务处理并发,或者tcp占用内存什么就不说了,在下也不怎么会。

强烈说下第二种原因:
当一个物体和服务端连接是正常的,但是当服务端或者物体在一定的时间内没有响应就会断开连接,这就是所谓的“ 心跳 ”!!!

就像这样,需要set一堆参数,其中“heartbeat_idle_time,heartbeat_check_interval”需要配合使用,文档连接: swoole文档-heartbeat_idle_time ,设置“heartbeat_idle_time”超出600秒才会断开,否则物体在30秒说着是50秒没有接收到响应就不会出现断开的情况了。

网上有一种方式是这样的:

根据业务自定。

以上是关于tcp连接的断开的主要内容,如果未能解决你的问题,请参考以下文章

TCP的连接与断开

TCP的连接与断开

tcp长连接保持多久

详解TCP四次挥手(断开TCP连接过程)

怎样强制断开TCP连接

TCP连接的建立和断开