189 8069 5689

go语言tcp断开 golang tcp

tcp连接的断开

TCP的断开就是经过四次挥手:

成都创新互联公司是一家从事企业网站建设、成都做网站、成都网站制作、成都外贸网站建设、行业门户网站建设、网页设计制作的专业网站制作公司,拥有经验丰富的网站建设工程师和网页设计人员,具备各种规模与类型网站建设的实力,在网站建设领域树立了自己独特的设计风格。自公司成立以来曾独立设计制作的站点上1000+。

这是正常的情况,客户端主动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 秒才可以发现一个「死亡」连接。

当然这个时间也可以自己配置。

【golang】高并发下TCP常见问题解决方案

首先,看一下TCP握手简单描绘过程:

其握手过程原理,就不必说了,有很多详细文章进行叙述,本文只关注研究重点。

在第三次握手过程中,如果服务器收到ACK,就会与客户端建立连接,此时内核会把连接从半连接队列移除,然后创建新的连接,并将其添加到全连接队列,等待进程调用。

如果服务器繁忙,来不及调用连接导致全连接队列溢出,服务器就会放弃当前握手连接,发送RST给客户端,即connection reset by peer。

在linux平台上,客户端在进行高并发TCP连接处理时,最高并发数量都要受系统对用户单一进程同时打开文件数量的限制(这是因为系统每个TCP都是SOCKET句柄,每个soker句柄都是一个文件),当打开连接超过限制,就会出现too many open files。

使用下指令查看最大句柄数量:

增加句柄解决方案

tcp为什么客户端断开连接后服务器陷入死循环

无法进入。tcp是传输控制协议,tcp的客户端断开连接之后服务器陷入死循环的原因是tcp无法进入客户端,属于是正常现象。传输控制协议是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC793定义。


文章名称:go语言tcp断开 golang tcp
地址分享:http://cdxtjz.cn/article/ddgpeoo.html

其他资讯