linux tcp优雅关闭,优雅地关闭Socket;检测非正常断开的TCP连接

2024-03-26 15:50

本文主要是介绍linux tcp优雅关闭,优雅地关闭Socket;检测非正常断开的TCP连接,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

--------------------------------------------------------------------------------------------------------------------------------------

[转载声明] 本文所有版权归原作者所有;如本文原作者不认可转载,请联系本空间删除。

[相关资源]  NA

--------------------------------------------------------------------------------------------------------------------------------------

如何优雅地关闭一个socket

[来 源:吃多了没事干(http://hi.baidu.com/firebird/blog/item/b005d562c332a9dde7113aab.html) ]

最近在windows编程时需要考虑到“如何优雅地关闭一个socket”,查阅了一些资料,现将查到的相关资料做个汇编,希望能对后来者有所帮助(比较懒,所以英文资料没有翻译:-))

1. 关闭Socket时究竟做了什么

关闭socket分为主动关闭(Active closure)和被动关闭(Passive closure)两种情况。前者是指有本地主机主动发起的关闭;而后者则是指本地主机检测到远程主机发起关闭之后,作出回应,从而关闭整个连接。

其状态图如下图所示:

0818b9ca8b590ca3270a3433284dd417.png

起初每个socket都是CLOSED状态,当客户端初使化一个连接,他发送一个SYN包到服务器,客户端进入SYN_SENT状态。

服务器接收到SYN包,反馈一个SYN-ACK包,客户端接收后返馈一个ACK包客户端变成ESTABLISHED状态,如果长时间没收到SYN-ACK 包,客户端超时进入CLOSED状态。

当服务器绑定并监听某一端口时,socket的状态是LISTEN,当客户企图建立连接时,服务器收到一个SYN包,并反馈SYN-ACK包。服务器状态变成SYN_RCVD,当客户端发送一个ACK包时,服务器socket变成ESTABLISHED状态。

当一个程序在ESTABLISHED状态时有两种图径关闭它, 第一是主动关闭,第二是被动关闭。如果你要主动关闭的话,发送一个FIN包。当你的程序closesocket或者shutdown(标记),你的程序发 送一个FIN包到peer,你的socket变成FIN_WAIT_1状态。peer反馈一个ACK包,你的socket进入FIN_WAIT_2状态。 如果peer也在关闭连接,那么它将发送一个FIN包到你的电脑,你反馈一个ACK包,并转成TIME_WAIT状态。

TIME_WAIT状 态又号2MSL等待状态。MSL意思是最大段生命周期(Maximum Segment Lifetime)表明一个包存在于网络上到被丢弃之间的时间。每个IP包有一个TTL(time_to_live),当它减到0时则包被丢弃。每个路由 器使TTL减一并且传送该包。当一个程序进入TIME_WAIT状态时,他有2个MSL的时间,这个充许TCP重发最后的ACK,万一最后的ACK丢失 了,使得FIN被重新传输。在2MSL等待状态完成后,socket进入CLOSED状态。

被动关闭:当程序收到一个FIN包从peer,并 反馈一个ACK包,于是程序的socket转入CLOSE_WAIT状态。因为peer已经关闭了,所以不能发任何消息了。但程序还可以。要关闭连接,程 序自已发送给自已FIN,使程序的TCP socket状态变成LAST_ACK状态,当程序从peer收到ACK包时,程序进入CLOSED状态。

2. Winsock2 API中的相关函数

先当然是查MSDN,看到winsocks2 API中的相关函数有:closesocket,shutdown,WSASendDisconnect. 我大致说一下,具体详细的资料还请自行查MSDN.

int closesocket(SOCKET s)的作用是关闭指定的socket,并且回收其所有的资源。

int shutdown(SOCKET s,  int how)则是禁止在指定的socket s上禁止进行由how指定的操作,但并不对资源进行回收,shutdown之后而closesocket之前s还不能再次connect或者 WSAConnect.

intWSASendDisconnect(SOCKET s,  LPWSABUF lpOutboundDisconnectData)则和shutdown基本类似,稍有不同的就是WSASendDisconnect函数多了一个lpOutboundDisconnectData参 数,可以允许发送“断开数据”(disconnect data).但MSDN上写了“The native implementation of TCP/IP on Windows does not support disconnect data.”,所以一般我们就用shutdown函数就行了。

3. Socket的优雅关闭

在 MSDN中对shutdown函数中的Remarks部分有下面一段话,指出了如何进行一次优雅的slcket关闭:

To assure that all data is sent and received on a connected socket before it is closed, an application should use shutdown to close connection before calling closesocket. For example, to initiate a graceful disconnect:

1. Call WSAAsyncSelect to register for FD_CLOSE notification.

2. Call shutdown with how=SD_SEND.

3. When FD_CLOSE received, call recv until zero returned, or SOCKET_ERROR.

4. Call closesocket.

closesocket 的行为也是随setsockopt()中参数的不同而有不同的表现,这里影响它的行为的主要就是那个linger结构。

SO_DONTLINGER 若为真,则SO_LINGER选项被禁止。

SO_LINGER 延迟关闭连接 struct linger

上面这两个选项影响close行为

选项 间隔 关闭方式 等待关闭与否

SO_DONTLINGER 不关心 优雅 否

SO_LINGER 零 强制 否

SO_LINGER 非零 优雅 是

若 设置了SO_LINGER(亦即linger结构中的l_onoff域设为非零),并设置了零超时间隔,则closesocket()不被阻塞立即执行, 不论是否有排队数据未发送或未被确认。这种关闭方式称为“强制”或“失效”关闭,因为套接口的虚电路立即被复位,且丢失了未发送的数据。在远端的recv ()调用将以WSAECONNRESET出错。

若设置了SO_LINGER并确定了非零的超时间隔,则closesocket()调用阻塞进 程,直到所剩数据发送完毕或超时。这种关闭称为“优雅的”关闭。请注意如果套接口置为非阻塞且SO_LINGER设为非零超时,则closesocket ()调用将以WSAEWOULDBLOCK错误返回。

若在一个流类套接口上设置了SO_DONTLINGER(也就是说将linger结构的 l_onoff域设为零),则closesocket()调用立即返回。但是,如果可能,排队的数据将在套接口关闭前发送。请注意,在这种情况下 WINDOWS套接口实现将在一段不确定的时间内保留套接口以及其他资源,这对于想用所以套接口的应用程序来说有一定影响。

所以一般来说,不应该把linger设置为SO_LINGER 并且设置timeout为0,这样的话,当本地主机调用closesocket时将会造成一个“强制”或“失效”的非优雅关闭。可以根据实际情况设置为另外两种情况。

--------------------------------------------------------------------------------------------------------------------------------------

[转]怎样及时检测出非正常断 开的TCP连接 作者:在水一鱼(powercc@21cn.com)

[来 源:吃多了没事干(http://hi.baidu.com/firebird/blog/item /5841c917042d2b09c93d6dbf.html) ] 此处的”非正常断开”指TCP连接不是以优雅的方式断开,如网线故障等物理链路的原因,还有突然主机断电等原因 有两种方法可以检测:1.TCP连接双方定时发握手消息 2.利用TCP协议栈中的KeepAlive探测 第二种方法简单可靠,只需对TCP连接两个Socket设定KeepAlive探测,所以本文只讲第二种方法在Linux,Window2000下的实现 (在其它的平台上没有作进一步的测试) windows 2000平台下 //定义结构及宏 struct TCP_KEEPALIVE { u_longonoff; u_longkeepalivetime; u_longkeepaliveinterval; } ; #define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4) //KeepAlive实现 TCP_KEEPALIVE inKeepAlive = {0}; //输入参数 unsigned long ulInLen = sizeof(TCP_KEEPALIVE); TCP_KEEPALIVE outKeepAlive = {0}; //输出参数 unsigned long ulOutLen = sizeof(TCP_KEEPALIVE); unsigned long ulBytesReturn = 0; //设置socket的keep alive为5秒,并且发送次数为3次 inKeepAlive.onoff = 1; inKeepAlive.keepaliveinterval = 5000; //两次KeepAlive探测间的时间间隔 inKeepAlive.keepalivetime = 5000; //开始首次KeepAlive探测前的TCP空闭时间 if (WSAIoctl((unsigned int)s, SIO_KEEPALIVE_VALS, (LPVOID)&inKeepAlive, ulInLen, (LPVOID)&outKeepAlive, ulOutLen, &ulBytesReturn, NULL, NULL) == SOCKET_ERROR) { ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%P|%t) /WSAIoctl failed. error code(%d)!/n"),WSAGetLastError())); } Linux平台下 #include …… KeepAlive实现 //下面代码要求有ACE,如果没有包含ACE,则请把用到的ACE函数改成linux相应的接口 int keepAlive = 1;//设定KeepAlive int keepIdle = 5;//开始首次KeepAlive探测前的TCP空闭时间 int keepInterval = 5;//两次KeepAlive探测间的时间间隔 int keepCount = 3;//判定断开前的KeepAlive探测次数 if(setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(void*)&keepAlive,sizeof(keepAlive)) == -1) { ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%P|%t) setsockopt SO_KEEPALIVE error!/n"))); } if(setsockopt(s,SOL_TCP,TCP_KEEPIDLE,(void *)&keepIdle,sizeof(keepIdle)) == -1) { ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%P|%t) setsockopt TCP_KEEPIDLE error!/n"))); } if(setsockopt(s,SOL_TCP,TCP_KEEPINTVL,(void *)&keepInterval,sizeof(keepInterval)) == -1) { ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%P|%t) setsockopt TCP_KEEPINTVL error!/n"))); } if(setsockopt(s,SOL_TCP,TCP_KEEPCNT,(void *)&keepCount,sizeof(keepCount)) == -1) { ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%P|%t)setsockopt TCP_KEEPCNT error!/n")));

这篇关于linux tcp优雅关闭,优雅地关闭Socket;检测非正常断开的TCP连接的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

W外链微信推广短连接怎么做?

制作微信推广链接的难点分析 一、内容创作难度 制作微信推广链接时,首先需要创作有吸引力的内容。这不仅要求内容本身有趣、有价值,还要能够激起人们的分享欲望。对于许多企业和个人来说,尤其是那些缺乏创意和写作能力的人来说,这是制作微信推广链接的一大难点。 二、精准定位难度 微信用户群体庞大,不同用户的需求和兴趣各异。因此,制作推广链接时需要精准定位目标受众,以便更有效地吸引他们点击并分享链接

linux-基础知识3

打包和压缩 zip 安装zip软件包 yum -y install zip unzip 压缩打包命令: zip -q -r -d -u 压缩包文件名 目录和文件名列表 -q:不显示命令执行过程-r:递归处理,打包各级子目录和文件-u:把文件增加/替换到压缩包中-d:从压缩包中删除指定的文件 解压:unzip 压缩包名 打包文件 把压缩包从服务器下载到本地 把压缩包上传到服务器(zip

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

烟火目标检测数据集 7800张 烟火检测 带标注 voc yolo

一个包含7800张带标注图像的数据集,专门用于烟火目标检测,是一个非常有价值的资源,尤其对于那些致力于公共安全、事件管理和烟花表演监控等领域的人士而言。下面是对此数据集的一个详细介绍: 数据集名称:烟火目标检测数据集 数据集规模: 图片数量:7800张类别:主要包含烟火类目标,可能还包括其他相关类别,如烟火发射装置、背景等。格式:图像文件通常为JPEG或PNG格式;标注文件可能为X

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

Linux服务器Java启动脚本

Linux服务器Java启动脚本 1、初版2、优化版本3、常用脚本仓库 本文章介绍了如何在Linux服务器上执行Java并启动jar包, 通常我们会使用nohup直接启动,但是还是需要手动停止然后再次启动, 那如何更优雅的在服务器上启动jar包呢,让我们一起探讨一下吧。 1、初版 第一个版本是常用的做法,直接使用nohup后台启动jar包, 并将日志输出到当前文件夹n