怎样实时判断socket连接状态?

客户端网络socket判定超时(TCP) 网络socket是整个传输层的基础,几乎所有的应用层协议都要经过该层来传输。下面以基于TCP的客户端在阻塞与非阻塞两个模式下的超时判断。一、阻塞socket采用setsockopt。SO_SNDTIMEO:限制send超时。SO_RCVTIMEO:限制recv超时对于connect的超时控制,还需要首先将socket转为非阻塞模型,处理完毕后(见下面二),再转换为阻塞socket,进行发送与接收的... 阅读详情
AI摘要

本文详细阐述了在编程中如何通过各种方法判断socket连接是否因对端异常断开,包括recv返回值、TCP_INFO结构、select行为、SO_KEEPALIVE设置、心跳检测以及TCP_USER_TIMEOUT。重点讲解了不同情况下的解决方案和注意事项。

摘自:https://www.cnblogs.com/embedded-linux/p/7468442.html

  • 对端正常close socket,或者进程退出(正常退出或崩溃),对端系统正常关闭

这种情况下,协议栈会走正常的关闭状态转移,使用epoll的话,一般要判断如下几个情况

    • 处理可读事件时,在循环read后,返回结果为0
    • 处理可写事件时,write返回-1,errno为EPIPE
    • EPOLLERR或EPOLLHUP或事件
  • 对端非正常断开,比如服务器断电,网线被拔掉

这种情况下,协议栈无法感知,SO_KEEPALIVE这个选项的超时事件太长并不实用,一般还是以应用层的heartbeat来及时发现。

 

下面来罗列一下判断远端已经断开的方法:

法一:

当recv()返回值小于等于0时,socket连接断开。但是还需要判断 errno是否等于 EINTR,如果errno == EINTR 则说明recv函数是由于程序接收到信号后返回的,socket连接还是正常的,不应close掉socket连接。

 

法二:

  struct tcp_info info; 
  int len=sizeof(info); 
  getsockopt(sock, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len);
  if((info.tcpi_state==TCP_ESTABLISHED))  则说明未断开  else 断开

函数封装,单独使用(没有使用read、write、select时),判读网络是否断开。 

 

法三:

若使用了select等系统函数,若远端断开,则select返回1,recv返回0则断开。其他注意事项同法一。

 

法四:

int keepAlive = 1; // 开启keepalive属性
int keepIdle = 60; // 如该连接在60秒内没有任何数据往来,则进行探测
int keepInterval = 5; // 探测时发包的时间间隔为5 秒
int keepCount = 3; // 探测尝试的次数.如果第1次探测包就收到响应了,则后2次的不再发.

setsockopt(rs, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));
setsockopt(rs, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle));
setsockopt(rs, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));
setsockopt(rs, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));

设置后,若断开,则在使用该socket读写时立即失败,并返回ETIMEDOUT错误

任何一端有数据发送就不会启动keepalive,参考:通过设置TCP_USER_TIMEOUT参数来判断tcp连接是否断开。

unsigned int timeout = 1000;   //值为数据包被发送后未接收到ACK确认的最大时长,以毫秒
                                    //为单位,例如设置为timeout时,代表如果发送出去的数据包
                                    //在timeout毫秒内未收到ACK确认,则下一次调用send或者recv,
                                    //函数会返回-1,errno设置为ETIMEOUT,代表connection timeout。

//使用TCP Keep-alive加上TCP_USER_TIMEOUT机制,就可以完美解
//决通信对端异常断网、掉电的情况下,连接被长期挂起的问题了。
setsockopt(socket_fd, IPPROTO_TCP, 18, &timeout, sizeof(timeout));
//setsockopt(socket_fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout, sizeof(timeout));

法五:

自己实现一个心跳检测,一定时间内未收到自定义的心跳包则标记为已断开。

 

参考:

1. 知乎:怎样实时判断socket链接状态?

2. 知乎:socket长连接是否会超时?连接中断,客户端或者服务器端是否一定能得到通知呢?

3. 如何判断SOCKET已经断开

4. TCP socket如何判断连接断开

5. 服务器中判断客户端socket断开连接的方法

6. tcp 服务端如何判断客户端断开连接

 

SOCKET【3】-select+getsockopt客户端检测connect是否成功 文章目录前言一、使用`select+getsockopt`如何知道是否真的成功的连接到远程服务器?1.1 connect 返回的几种情况:1.2 针对1.1中的第二种情况的处理三、 `getsockopt`获取`SO_ERROR`等于0一定是没有问题吗?四、 select 服务器如何编程能快速知道对端是否已经断开?总结 前言 使用select+getsockopt如何知道是否真的成功的连接到远程服务器? 客户端一旦链接成功服务器 fd 的状态是什么?是确定不变的?还是多种多样的? getsockopt获 阅读详情

相关推荐

MFC疑难注解:CAsyncSocket及CSocket

MFC疑难注解:CAsyncSocket及CSocketfangle 2006-07-27MFC对SOCKET编程的支持其实是很充分的,然而其文档是语焉不详的。以至于大多数用VC编写的功能稍复杂的网络程序,还是使用API的。故CAsyncSocket及CSocket事实上成为疑难,群众多敬而远之。余好事者也,不忍资源浪费,特为之注解。一、CAsyncSocket与CSocket的区别前

不甘碌碌老,结庐铸宝刀 8513

(read/write、select、getsockopt、signal)实时判断socket连接状态/是否断开

为什么socket服务器断开之后客户端还能发送一次数据呢? 文章目录为什么socket服务器断开之后客户端还能发送一次数据呢?一、了解背后的原因1、客户端是如何将数据发送给服务器端的?(服务器端发客户端同理)二、解决办法 最近遇到一个大坑:发现服务器端断开连接时,客户端还能write成功一次,不过服务器端是没有收到的,而且我的服务器数据库里面也没有保存。最后一次能write成功估计是将数据写入到缓冲区里面了,但是客户端还没确定服务器是否已经断开了连接,所以能write成功。因为项目对数据比较敏感,没有成功发

weixin_45880057的博客 7164

RenderDoc实战:5分钟搞定安卓Vulkan应用抓帧(含常见连接失败排查)

本文详细介绍了如何使用RenderDoc工具对安卓Vulkan应用进行抓帧分析,包括环境配置、完整抓帧流程及常见连接问题的解决方案。通过实战案例和高级技巧,帮助开发者快速定位渲染问题和性能瓶颈,提升移动图形开发效率。

weixin_28318011的博客 282

判断SOCKET连接状态

第四种是本人认为最好的 1. 用read函数来判断   读到长度0不能断定是已经断开.除非是-1,才代表输入流已经被关闭,说名socket已经close,而且关键在于你怎么读,实际上应该是一个单独的线程一直在读,因为你无法预先知道能不能一次将发过来的包读完,也无法知道一次是不是读完整了包,所以线称一直循环在读并且一直在解包.这样即能知道什么时候server断,也完成了消息的解读,我的

FrankieWang008的专栏 2万+

文本纠错项目代码调试

文本纠错项目调试

m0_67084346的博客 868

怎样实时判断socket连接状态

摘自:怎样实时判断socket连接状态? - yuxi_o - 博客园 对端正常close socket,或者进程退出(正常退出或崩溃),对端系统正常关闭 这种情况下,协议栈会走正常的关闭状态转移,使用epoll的话,一般要判断如下几个情况 处理可读事件时,在循环read后,返回结果为0 处理可写事件时,write返回-1,errno为EPIPE EPOLLERR或EPOLLHUP或事件 对端非正常断开,比如服务器断电,网线被拔掉 这种情况下,协议栈无法感知,SO_KEEPALIVE这个

kv110的专栏 6876

PyBioMed学习

PyProtein。

weixin_63016274的博客 1401

判断 Socket 的实时连接状态(心跳包)

文章目录一、问题引入二、心跳包 一、问题引入 socket.isConnected()或者socket.isClosed()等方法都是访问socket在内存驻留的状态,当socket 和服务器端建立链接后,即使 socket 链接断掉了,调用上面的方法返回的仍然是链接时的状态,而不是socket的实时链接状态 例如如下实例: 客户端: public class Client{ public...

南淮北安的博客 7633

SAP ABAP VL09 BAPI VL 216

ls_batch_item-fact_unit_denom = ls_lips_split-umvkn. "销售数量转换为 SKU 的值(分母)ls_batch_item-fact_unit_nom = ls_lips_split-umvkz. "销售数量转换成SKU的分子(因子)ls_batch_item-sales_unit_iso = ls_lips_split-meins. "被拆分DN基本单位。

ChampaignWolf的专栏 2300

ubuntu 20.04 搭建多用户远程桌面共享及同时在线使用

摘要:本文介绍了在物理机上配置远程桌面访问的完整流程。通过setup_xrdp.sh脚本自动安装xrdp服务,修改配置文件并开放3389端口。同时提供了用户管理脚本:add_rdp_users.sh用于创建带sudo权限的远程用户,del_rdp_users.sh用于删除用户及主目录。还包含批量操作脚本add_rdp_all.sh和del_rdp_all.sh,支持一次性创建/删除多个用户(如dev1-dev5),所有用户密码统一设置为111111。完整方案实现了远程桌面环境的快速部署和用户集中管理。

623

python判断sqlite连接状态_怎样实时判断socket连接状态?

对端正常close socket,或者进程退出(正常退出或崩溃),对端系统正常关闭这种情况下,协议栈会走正常的关闭状态转移,使用epoll的话,一般要判断如下几个情况处理可读事件时,在循环read后,返回结果为0处理可写事件时,write返回-1,errno为EPIPEEPOLLERR或EPOLLHUP或事件对端非正常断开,比如服务器断电,网线被拔掉这种情况下,协议栈无法感知,SO_KEEPALI...

weixin_39644915的博客 486

数据挖掘7、银行精准营销

利用数据挖掘技术,对银行已有数据进行分析,对客户进行识别,对客户是否能够进行存款精准营销Windows11。

m0_63099685的博客 395

C#怎么判断一个Socket是否连接

判断Socket是否连接上,需要通过发包来确认: 1 // 检查一个Socket是否可连接 2 private bool IsSocketConnected(Socket client) 3 { 4 bool blockingState = client.Blocking; 5

wilsonke的专栏 1万+

BLDC控制实验:方波、霍尔、开环、定速、正转

本文记录博主学习BLDC控制软件的过程。 文章目录1 概述2 软件架构及工具链2.1 软件架构2.2 工具链3 底层代码生成3.1 时钟配置3.2 按键输入配置 1 概述 本文是博主第一次做BLDC控制实验,目的仅仅是写代码让BLDC转起来,而暂时不考虑其他复杂的需求。 控制的方法是比较简单的六步换相法。利用电机内部的霍尔传感器,通过参考电机厂家给出的二二导通换相表,生成方波来控制电机。第一次实验为了简化需求,只考虑开环、定速、正转的情况: 开环:不考虑速度反馈,直接给PWM让电机转起来; 定速:不考虑速

u013288925的博客 1万+

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

C#服务端判断客户端socket是否已断开的方法

刚开始,用Socket类的Connected属性来实现,却发现行不通,connected只表示是在上次还是操作时连接到远程主机。如果在这之后[连接的另一方]断开了,它还一直返回true, 除非你再通过socket来发送数据。所以通过个属性来判断是行不通的!后来有人说可以用Socket.Available属性来判断,Socket.Available表示获取已经从网络接收且可供读取的数据量。 msdn中说:如果[连接的另一方]断开了,它就会抛出异常。然而,这个BUG报告(htt...

ba_wang_mao的专栏 7470

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

c#判断socket是否还连接着

刚开始用的是Socket.Connected。但是,msdn上说:“ The Connected property gets the connection state of the Socket as of the last I/O operation. When it returns false, the Socket was either never connected, or is no

pigHead_chen的专栏 4372

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

判断socket连接状态

socket有这么几个方法 socket.isClosed(),socket.isConnected(),socket.isInputShutdown(),isOutputShutdown() 当我们客户端socket连接上服务器的时候这个既状态分别为,false,true,false,false。但是当入服务器突然断开的时候,他们的状态依然是false,true,false,false。那我...

iteye_2459的博客 1295

Socket.Connected 不能作为TCP连接的判断依据

C# Socket.Connected 不能作为TCP连接的判断依据

wangnaisheng的专栏 1470

比isConnected()更靠谱的的获取socket实时连接状态!

看到这个标题,预计非常多人会说用socket.isConnected()或者socket.isClosed()等方法来推断即可了,但其实这些方法都是訪问socket在内存驻留的状态,当socket和server端建立链接后,即使socket链接断掉了,调用上面的方法返回的仍然是链接时的状态,而不是socket的实时链接状态。以下给出样例证明这一点。   server端: ...

weixin_30827565的博客 126

不应该使用Connected属性作为Socket是否连接上的依据

最近在做一个接口,用到了Socket异步通信。调试了3天了,一直将Socket的Connected属性作为客户端和服务器端是否连接上的依据。今天发现我错了。 下面是从一个csdn博友写的,很好。http://blog.youkuaiyun.com/xiaobai1593/article/details/7285930 Connected属性获取截止到最后的 I/O 操作时Socket的连接状态。当它返回false时,表明Socket要么从未连接,要么已...

ba_wang_mao的专栏 361
上一篇: 在Linux系统里使用SS命令获取TCP RTT
下一篇: Linux 下的 AddressSanitizer
RyanLeiWang
博客等级 码龄20年 184粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值