TCP连接被意外重置的原因

2024-06-15 01:48
文章标签 连接 tcp 重置 原因 意外

本文主要是介绍TCP连接被意外重置的原因,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

明显服务器端上层读取过慢了, 窗口填满了

今天在做服务器压力测试的时候,出现了很奇怪的情况,与服务器建立连接会成功,但是很快会被重置(RESET)掉。花了半天时间,终于找到原因所在,我把过程和结果写下来与大家分享。

 

    服务器正常逻辑是:接受连接,等待用户注册报文,处理其他请求,如果连接一段时间没有活动,则主动关闭连接。

 

    客户端逻辑是:与服务器建立连接后,马上发送注册报文,然后每隔一段时间发送一个请求。有上万个客户端同时连接一个服务器,当连接出现错误时,马上重新连接。

 

    出现错误时,客户端会报告下面一连串错误:

 

recv: Connection reset by peer
recv: Connection reset by peer
recv: Connection reset by peer
recv: Connection reset by peer
recv: Connection reset by peer
recv: Connection reset by peer
recv: Connection reset by peer
recv: Connection reset by peer
recv: Connection reset by peer
recv: Connection reset by peer
recv: Connection reset by peer
recv: Connection reset by peer
recv: Connection reset by peer
recv: Connection reset by peer
recv: Connection reset by peer
recv: Connection reset by peer
recv: Connection reset by peer
recv: Connection reset by peer
recv: Connection reset by peer

 

    进一步的测试发现只有在客户端数目超过一定数量才会出现这样的情况,于是联想到Linux进程打开文件描述符(Linux下套接字也是一种文件描述符)的数量限制(前几天刚刚增加了这个数量限制),但是到底有什么联系不知道。

 

    开始以为服务器程序逻辑主动关闭了连接,但是根据抓包的结果,服务器根本就没有发送TCP FIN报文,下面是一个典型的连接建立与重置的过程:

 

14:01:03.567888 IP 192.168.6.45.36692 > 192.168.6.46.8080: S 1231228012:1231228012(0) win 5792 <mss 1460,sackOK,timestamp 174530727 168899918,nop,wscale 8>
14:01:03.567969 IP 192.168.6.46.8080 > 192.168.6.45.36692: S 909133089:909133089(0) ack 1231228013 win 5792 <mss 1460,sackOK,timestamp 168900338 174530727,nop,wscale 8>
14:01:03.567978 IP 192.168.6.45.36692 > 192.168.6.46.8080: . ack 1 win 23 <nop,nop,timestamp 174530727 168900338>
14:01:03.568022 IP 192.168.6.45.36692 > 192.168.6.46.8080: P 1:76(75) ack 1 win 23 <nop,nop,timestamp 174530727 168900338>
14:01:03.568110 IP 192.168.6.46.8080 > 192.168.6.45.36692: . ack 76 win 23 <nop,nop,timestamp 168900338 174530727>
14:01:03.568769 IP 192.168.6.46.8080 > 192.168.6.45.36692: R 1:1(0) ack 76 win 23 <nop,nop,timestamp 168900338 174530727>

 

    检查服务器的日志,也没有主动关闭连接的记录,甚至并没有接受到新的连接。这说明连接是由底层协议栈关闭的,但协议栈为什么会主动关闭呢?

 

    用telnet连接服务器,也不正常,但是是被正常关闭的(有正常的FIN序列),而不是重置。

 

    是否与侦听套接字的就绪连接队列长度有关?但是连接队列满时,协议栈不做任何操作,而是让客户端超市重发SYN报文,与出现的情况不一致。

 

    看来还是有打开文件描述符的数量限制有关,那么不能再打开文件描述符时,会出现什么情况呢?为什么telnet连接会出现不同的情形呢?对这些问题的回答就要透过现象看本质了,我的分析如下:

 

    首先,连接确实是建立了,说明协议栈是接受了这个连接的,当然,应用程序肯定没有接受,否则打开文件描述符数目超过上限了。另一方面,协议栈当然要关闭这个连接,但是没有立即关闭,应该是在应用程序接受连接时(accept)关闭(尚未验证),进一步跟踪,accept会产生too many open files错误。这也说明套接字这个文件描述符是在accept时打开的,在协议栈中建立的连接并没有对应的套接字描述符。

 

        telnet连接的不同之处在于没有向服务器发送数据,此时采用正常方式关闭,这是协议的要求还是Linux实现的特例没有考证过。

 

        还有另外一个结论是在accept之前收到的数据仍然会被接受并应答,并且连接上的数据是存储在协议栈中的,这符合我先前的概念。


这篇关于TCP连接被意外重置的原因的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1062092

相关文章

C#连接SQL server数据库命令的基本步骤

《C#连接SQLserver数据库命令的基本步骤》文章讲解了连接SQLServer数据库的步骤,包括引入命名空间、构建连接字符串、使用SqlConnection和SqlCommand执行SQL操作,... 目录建议配合使用:如何下载和安装SQL server数据库-CSDN博客1. 引入必要的命名空间2.

Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式

《Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式》本文详细介绍如何使用Java通过JDBC连接MySQL数据库,包括下载驱动、配置Eclipse环境、检测数据库连接等关键步骤,... 目录一、下载驱动包二、放jar包三、检测数据库连接JavaJava 如何使用 JDBC 连接 mys

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景

SpringBoot连接Redis集群教程

《SpringBoot连接Redis集群教程》:本文主要介绍SpringBoot连接Redis集群教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 依赖2. 修改配置文件3. 创建RedisClusterConfig4. 测试总结1. 依赖 <de

SpringSecurity显示用户账号已被锁定的原因及解决方案

《SpringSecurity显示用户账号已被锁定的原因及解决方案》SpringSecurity中用户账号被锁定问题源于UserDetails接口方法返回值错误,解决方案是修正isAccountNon... 目录SpringSecurity显示用户账号已被锁定的解决方案1.问题出现前的工作2.问题出现原因各

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

MyBatis Plus 中 update_time 字段自动填充失效的原因分析及解决方案(最新整理)

《MyBatisPlus中update_time字段自动填充失效的原因分析及解决方案(最新整理)》在使用MyBatisPlus时,通常我们会在数据库表中设置create_time和update... 目录前言一、问题现象二、原因分析三、总结:常见原因与解决方法对照表四、推荐写法前言在使用 MyBATis

java连接opcua的常见问题及解决方法

《java连接opcua的常见问题及解决方法》本文将使用EclipseMilo作为示例库,演示如何在Java中使用匿名、用户名密码以及证书加密三种方式连接到OPCUA服务器,若需要使用其他SDK,原理... 目录一、前言二、准备工作三、匿名方式连接3.1 匿名方式简介3.2 示例代码四、用户名密码方式连接4

IDEA中Maven Dependencies出现红色波浪线的原因及解决方法

《IDEA中MavenDependencies出现红色波浪线的原因及解决方法》在使用IntelliJIDEA开发Java项目时,尤其是基于Maven的项目,您可能会遇到MavenDependenci... 目录一、问题概述二、解决步骤2.1 检查 Maven 配置2.2 更新 Maven 项目2.3 清理本