没有任何关闭socket的日志,客户端和服务端进程都在, 网络连接完好, 为什么进行某操作后好好的tcp连接莫名其妙地断了呢?

本文主要是介绍没有任何关闭socket的日志,客户端和服务端进程都在, 网络连接完好, 为什么进行某操作后好好的tcp连接莫名其妙地断了呢?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        说明:本文只针对某个特定问题进行分析,定位出的最终结果不具有通用性, 但定位过程是可以揣摩揣摩的。

 

        遇到这样一个问题:没有任何关闭socket的日志,客户端和服务端进程都在, 网络连接完好, 为什么进行某操作后好好的tcp连接莫名其妙地断了呢? 而且这个问题必现。

        首先, 看日志, 没有close socket的任何日志, 而且, 可以确定的是, 如果代码有close socket的操作, 必定有日志输出。

        其次, 查看客户端和服务端进程, 发现进程都在, 进程开看起来安然无恙。

        最后, 经认真检查网络, 确认网络没有问题。

 

        那为什么好好的tcp连接说断就断了呢?  别多想, 抓包是唯一证据。 结果发现, 服务端主动断开了连接, 这就奇怪了, 服务端明明没有去close socket啊。 进一步发现, 服务端进程的进程号非常大, 于是猜想是不是服务端挂掉后又被拉起来了?  经简单确认, 果然如此。 从tcp连接好到坏的过程中, 服务端进程的进程号改变了,说明服务端进程死了又生。原来如此! 而且, 从日志中看, 确实有系统级的日志显示: 该进程挂了, 该进程又重新被拉起来了。

        我在Windows上来简单模拟一下这个场景。 服务端代码(服务端ip为192.168.1.102):

 

#include <stdio.h>
#include <winsock2.h> // winsock接口
#pragma comment(lib, "ws2_32.lib") // winsock实现int main()
{WORD wVersionRequested;  // 双字节,winsock库的版本WSADATA wsaData;         // winsock库版本的相关信息wVersionRequested = MAKEWORD(1, 1); // 0x0101 即:257// 加载winsock库并确定winsock版本,系统会把数据填入wsaData中WSAStartup( wVersionRequested, &wsaData );// AF_INET 表示采用TCP/IP协议族// SOCK_STREAM 表示采用TCP协议// 0是通常的默认情况unsigned int sockSrv = socket(AF_INET, SOCK_STREAM, 0);SOCKADDR_IN addrSrv;addrSrv.sin_family = AF_INET; // TCP/IP协议族addrSrv.sin_addr.S_un.S_addr = inet_addr("0.0.0.0"); // socket对应的IP地址addrSrv.sin_port = htons(8888); // socket对应的端口// 将socket绑定到某个IP和端口(IP标识主机,端口标识通信进程)bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));// 将socket设置为监听模式,5表示等待连接队列的最大长度listen(sockSrv, 5);SOCKADDR_IN addrClient;int len = sizeof(SOCKADDR);// sockSrv为监听状态下的socket// &addrClient是缓冲区地址,保存了客户端的IP和端口等信息// len是包含地址信息的长度// 如果客户端没有启动,那么程序一直停留在该函数处unsigned int sockConn = accept(sockSrv, (SOCKADDR*)&addrClient, &len);while(1){getchar();}closesocket(sockConn);closesocket(sockSrv);WSACleanup();return 0;
}

      启动服务端。

 

 

      客户端代码为(客户端ip为192.168.1.101):

 

#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")int main()
{WORD wVersionRequested;WSADATA wsaData;wVersionRequested = MAKEWORD(1, 1);WSAStartup( wVersionRequested, &wsaData );SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.1.102");addrSrv.sin_family = AF_INET;addrSrv.sin_port = htons(8888);connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));while(1){getchar();}closesocket(sockClient);WSACleanup();return 0;
}

       在客户端所在的电脑(也就是我现在写博客的电脑)上, 启动Wireshark抓包, 然后启动上述客户端。  这样就建立了tcp连接。

 

 

       然后, 我们关掉服务端, 也就是关掉那个黑色的框框。 抓包结果如下:

        抓包结果说明了一切。 跟网络相关的问题, 抓包是非常有说服力的。

 

        至于为什么服务端进程死而复生, 这不属于本文要讨论的问题(我还是说一下原因吧:是别的模块错发了信号,误杀了该服务端的进程, 然后系统又重新拉起了它)。 通过本文, 我只想说, bug的原因可能有很多种, 下结论时, 不要武断, 要避免教科书式的僵化、死板思维, 要灵活。 不要轻信任何人的“大概”、“也许”,“应该”式的描述, 要大胆假设, 小心求证。

        据我所知, 有很多公司, 搞bug要占据一半以上的时间, 有的部门, 甚至占到了80%以上, 有的更甚, 惨不忍睹。在这种情况下,  死板者死, 灵活者生。 有的bug开始看起来很难, 定位出原因后, 常常会让人哭笑不得, 有时候, 甚至容易笑掉大牙大笑 。

       OK,  先说这么多。

 

 

 

 

 

 

       

这篇关于没有任何关闭socket的日志,客户端和服务端进程都在, 网络连接完好, 为什么进行某操作后好好的tcp连接莫名其妙地断了呢?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Python如何精准判断某个进程是否在运行

《Python如何精准判断某个进程是否在运行》这篇文章主要为大家详细介绍了Python如何精准判断某个进程是否在运行,本文为大家整理了3种方法并进行了对比,有需要的小伙伴可以跟随小编一起学习一下... 目录一、为什么需要判断进程是否存在二、方法1:用psutil库(推荐)三、方法2:用os.system调用

Java程序进程起来了但是不打印日志的原因分析

《Java程序进程起来了但是不打印日志的原因分析》:本文主要介绍Java程序进程起来了但是不打印日志的原因分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java程序进程起来了但是不打印日志的原因1、日志配置问题2、日志文件权限问题3、日志文件路径问题4、程序

Java使用SLF4J记录不同级别日志的示例详解

《Java使用SLF4J记录不同级别日志的示例详解》SLF4J是一个简单的日志门面,它允许在运行时选择不同的日志实现,这篇文章主要为大家详细介绍了如何使用SLF4J记录不同级别日志,感兴趣的可以了解下... 目录一、SLF4J简介二、添加依赖三、配置Logback四、记录不同级别的日志五、总结一、SLF4J

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

QT进行CSV文件初始化与读写操作

《QT进行CSV文件初始化与读写操作》这篇文章主要为大家详细介绍了在QT环境中如何进行CSV文件的初始化、写入和读取操作,本文为大家整理了相关的操作的多种方法,希望对大家有所帮助... 目录前言一、CSV文件初始化二、CSV写入三、CSV读取四、QT 逐行读取csv文件五、Qt如何将数据保存成CSV文件前言

python logging模块详解及其日志定时清理方式

《pythonlogging模块详解及其日志定时清理方式》:本文主要介绍pythonlogging模块详解及其日志定时清理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录python logging模块及日志定时清理1.创建logger对象2.logging.basicCo

Python 中的 with open文件操作的最佳实践

《Python中的withopen文件操作的最佳实践》在Python中,withopen()提供了一个简洁而安全的方式来处理文件操作,它不仅能确保文件在操作完成后自动关闭,还能处理文件操作中的异... 目录什么是 with open()?为什么使用 with open()?使用 with open() 进行

通过Spring层面进行事务回滚的实现

《通过Spring层面进行事务回滚的实现》本文主要介绍了通过Spring层面进行事务回滚的实现,包括声明式事务和编程式事务,具有一定的参考价值,感兴趣的可以了解一下... 目录声明式事务回滚:1. 基础注解配置2. 指定回滚异常类型3. ​不回滚特殊场景编程式事务回滚:1. ​使用 TransactionT

Qt spdlog日志模块的使用详解

《Qtspdlog日志模块的使用详解》在Qt应用程序开发中,良好的日志系统至关重要,本文将介绍如何使用spdlog1.5.0创建满足以下要求的日志系统,感兴趣的朋友一起看看吧... 目录版本摘要例子logmanager.cpp文件main.cpp文件版本spdlog版本:1.5.0采用1.5.0版本主要

Java中使用Hutool进行AES加密解密的方法举例

《Java中使用Hutool进行AES加密解密的方法举例》AES是一种对称加密,所谓对称加密就是加密与解密使用的秘钥是一个,下面:本文主要介绍Java中使用Hutool进行AES加密解密的相关资料... 目录前言一、Hutool简介与引入1.1 Hutool简介1.2 引入Hutool二、AES加密解密基础