没有任何关闭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

相关文章

使用MongoDB进行数据存储的操作流程

《使用MongoDB进行数据存储的操作流程》在现代应用开发中,数据存储是一个至关重要的部分,随着数据量的增大和复杂性的增加,传统的关系型数据库有时难以应对高并发和大数据量的处理需求,MongoDB作为... 目录什么是MongoDB?MongoDB的优势使用MongoDB进行数据存储1. 安装MongoDB

Linux使用fdisk进行磁盘的相关操作

《Linux使用fdisk进行磁盘的相关操作》fdisk命令是Linux中用于管理磁盘分区的强大文本实用程序,这篇文章主要为大家详细介绍了如何使用fdisk进行磁盘的相关操作,需要的可以了解下... 目录简介基本语法示例用法列出所有分区查看指定磁盘的区分管理指定的磁盘进入交互式模式创建一个新的分区删除一个存

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

Golang操作DuckDB实战案例分享

《Golang操作DuckDB实战案例分享》DuckDB是一个嵌入式SQL数据库引擎,它与众所周知的SQLite非常相似,但它是为olap风格的工作负载设计的,DuckDB支持各种数据类型和SQL特性... 目录DuckDB的主要优点环境准备初始化表和数据查询单行或多行错误处理和事务完整代码最后总结Duck

C# 读写ini文件操作实现

《C#读写ini文件操作实现》本文主要介绍了C#读写ini文件操作实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录一、INI文件结构二、读取INI文件中的数据在C#应用程序中,常将INI文件作为配置文件,用于存储应用程序的

Python手搓邮件发送客户端

《Python手搓邮件发送客户端》这篇文章主要为大家详细介绍了如何使用Python手搓邮件发送客户端,支持发送邮件,附件,定时发送以及个性化邮件正文,感兴趣的可以了解下... 目录1. 简介2.主要功能2.1.邮件发送功能2.2.个性签名功能2.3.定时发送功能2. 4.附件管理2.5.配置加载功能2.6.

使用Python进行文件读写操作的基本方法

《使用Python进行文件读写操作的基本方法》今天的内容来介绍Python中进行文件读写操作的方法,这在学习Python时是必不可少的技术点,希望可以帮助到正在学习python的小伙伴,以下是Pyth... 目录一、文件读取:二、文件写入:三、文件追加:四、文件读写的二进制模式:五、使用 json 模块读写

Python使用qrcode库实现生成二维码的操作指南

《Python使用qrcode库实现生成二维码的操作指南》二维码是一种广泛使用的二维条码,因其高效的数据存储能力和易于扫描的特点,广泛应用于支付、身份验证、营销推广等领域,Pythonqrcode库是... 目录一、安装 python qrcode 库二、基本使用方法1. 生成简单二维码2. 生成带 Log

Java操作ElasticSearch的实例详解

《Java操作ElasticSearch的实例详解》Elasticsearch是一个分布式的搜索和分析引擎,广泛用于全文搜索、日志分析等场景,本文将介绍如何在Java应用中使用Elastics... 目录简介环境准备1. 安装 Elasticsearch2. 添加依赖连接 Elasticsearch1. 创

怎么关闭Ubuntu无人值守升级? Ubuntu禁止自动更新的技巧

《怎么关闭Ubuntu无人值守升级?Ubuntu禁止自动更新的技巧》UbuntuLinux系统禁止自动更新的时候,提示“无人值守升级在关机期间,请不要关闭计算机进程”,该怎么解决这个问题?详细请看... 本教程教你如何处理无人值守的升级,即 Ubuntu linux 的自动系统更新。来源:https://