C# Socket keeplive 心跳检测实例
版权声明:本文为CSDN博主「b哈利路亚d」的原创文章,重新编辑发布,请尊重原作者的劳动成果,转载的时候附上原文链接:https://blog.csdn.net/lanwilliam/article/details/51698807
Socket本身无法很好的捕获连接断开事件,或者说根本没这功能。总不能每次发生数据通讯时,通过异常来判断吧。
所以经过了各种测试及查询(这里还是要感谢国外的友人们,鄙视一下国人),总算找到一种相对稳定的方法。
该方法利用了tcp/ip协议本省的keep-alive规则。
keep-alive简单来说,就是tcp协议中制定的心跳检测,用来判断连接是否存活。默认是不启动的,需要进行设置。
serverFullAddr = new IPEndPoint(IPAddress.Any, portNo);//设置IP,端口
server = new TcpListener(serverFullAddr);
server.Start();
// 启用keep-alive
server.Server.IOControl(IOControlCode.KeepAliveValues, GetKeepAliveData(), null);
server.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
上面是server端演示代码,用的是tcplistener,毕竟比较方便。而且用来和DTU通讯的时候,使用的NetworkStream,这个相对好用
client = server.AcceptTcpClient();
// 启用keep-alive
client.Client.IOControl(IOControlCode.KeepAliveValues, GetKeepAliveData(), null);
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
上面是客户端启用的设置。
按照查询到的理论,应该任意一方面设置了就可以,不过我这里都启用了,姑且算保险吧。
然后就是IOControl设置的数据了。
private byte[] GetKeepAliveData()
{
uint dummy = 0;
byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
BitConverter.GetBytes((uint)3000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));//keep-alive间隔
BitConverter.GetBytes((uint)500).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);// 尝试间隔
return inOptionValues;
}
keep-alive如果使用windows默认,可能2个小时才会发送一次心跳,我这里检测设备在线,肯定不能这么长时间,我的读数频率都是以分钟作为单位的,出于各方面考虑
我这里设置的keep-alive每3秒发送一次。如果对方没有响应,每0.5秒后发送一次确认,如果连续3次没有回应,连接会自动变成TcpState.Established。
这里说一下,查询过程中发现很多人使用socket去poll来进行判断,在测试中,发现不好用,响应不及时,后来多方查找资料并测试,发现通过系统本身的连接来进行判断比较准确,方法如下:
/// <summary>
/// THIS FUNCTION WILL CHECK IF CLIENT IS STILL CONNECTED WITH SERVER.
/// </summary>
/// <returns>FALSE IF NOT CONNECTED ELSE TRUE</returns>
public bool isClientConnected(TcpClient ClientSocket)
{
IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[] tcpConnections = ipProperties.GetActiveTcpConnections();
foreach (TcpConnectionInformation c in tcpConnections)
{
TcpState stateOfConnection = c.State;
if (c.LocalEndPoint.Equals(ClientSocket.Client.LocalEndPoint) && c.RemoteEndPoint.Equals(ClientSocket.Client.RemoteEndPoint))
{
if (stateOfConnection == TcpState.Established)
{
return true;
}
else
{
return false;
}
}
}
return false;
}
这样解决办法就简单了。
单独写一个CheckAlive的线程进行检测,然后抛出事件并移除连接就ok。
public void StartCheckAlive()
{
Thread th = new Thread(new ThreadStart(CheckAlive));
th.IsBackground = true;
th.Start();
TCPLogger.Log("CheckAlive线程已启动");
}
private void CheckAlive()
{
Thread.Sleep(10000);
while(isListen)
{
try
{
lock (ClientList)
{
foreach (ClientItem item in ClientList)
{
//if (item.Client.Client.Poll(500, System.Net.Sockets.SelectMode.SelectRead) && (item.Client.Client.Available == 0))
if (!isClientConnected(item.Client))
{
removeQueue.Enqueue(item);
continue;
}
}
while (removeQueue.Count > 0)
{
ClientItem item = removeQueue.Dequeue();
clientList.Remove(item);
try
{
TCPLogger.Log("关闭客户端连接");
item.Client.Close();
}
catch (Exception ex)
{
TCPLogger.Log("关闭客户端连接", ex);
}
TCPLogger.Log("CheckAlive移除链接:" + item.RegCode);
if (OnClientRemoved != null)
OnClientRemoved(item.RegCode);
}
}
}catch(Exception e)
{
TCPLogger.Log("CheckAlive异常.", e);
}
Thread.Sleep(500);
}
}
C# Socket keeplive 心跳检测实例的更多相关文章
- socket心跳检测
一.什么是心跳检测 判断对方(设备,进程或其它网元)是否正常动行,一般采用定时发送简单的通讯包,如果在指定时间段内未收到对方响应,则判断对方已经当掉.用于检测TCP的异常断开. 基本原因是服务器端不能 ...
- Mina 系列(四)之KeepAliveFilter -- 心跳检测
Mina 系列(四)之KeepAliveFilter -- 心跳检测 摘要: 心跳协议,对基于CS模式的系统开发来说是一种比较常见与有效的连接检测方式,最近在用MINA框架,原本自己写了一个心跳协议实 ...
- 记录初试Netty(2)-服务端心跳检测
今天在在搭建的netty框架中添加心跳机制,特此记录一下: 1.什么是心跳机制? 心跳是在TCP长连接中,客户端和服务端定时向对方发送数据包通知对方自己还在线,保证连接的有效性的一种机制 在 ...
- websocket-heartbeat-js心跳检测库正式发布
前言: 两年前写了一篇websocket心跳的博客——初探和实现websocket心跳重连. 阅读量一直比较大,加上最近考虑写一个自己的npm包,因此就完成了一个websocket心跳的检测库.在这 ...
- wifidog源码分析 - 认证服务器心跳检测线程
引言 但wifidog启动时,会自动启动认证服务器心跳检测线程,此线程默认每隔60s与认证服务器交互一次,会将路由器的信息(系统启动时长,内存使用情况和系统平均负载)告知认证服务器,并通过一个&quo ...
- Netty实践二(心跳检测)
我们使用Socket通信一般经常会处理多个服务器之间的心跳检测,一般来讲,我们去维护服务器集群,肯定要有一台或几台服务器主机(Master),然后还应该有N台(Slave),那么我们的主机肯定要时时刻 ...
- 基于MINA实现server端心跳检测(KeepAliveFilter)
MINA自带了对心跳协议的支持,可以对心跳做出细致的配置,本文在次基础上实现了server端对client端的心跳检测. 在开始之前先简单介绍下keepAlive的机制: 首先,需要搞清楚TCP ke ...
- Netty--数据通信和心跳检测
数据通信 概述: netty的ReadTimeOut实现方案3 服务端: public class Server { public static void main(String[] args) th ...
- 切实解决socket连接掉线检测
原文:切实解决socket连接掉线检测 版权声明:欢迎转载,但是请保留出处说明 https://blog.csdn.net/lanwilliam/article/details/51698807 新公 ...
随机推荐
- 修改Docker容器启动配置参数
有时候,我们创建容器时忘了添加参数 --restart=always ,当 Docker 重启时,容器未能自动启动, 现在要添加该参数怎么办呢,方法有二: 1.Docker 命令修改 docker c ...
- 【Beta】Scrum meeting 7
目录 写在前面 进度情况 任务进度表 Beta-1阶段燃尽图 遇到的困难 照片 commit截图记录 后端代码仓库 技术博客 写在前面 例会时间:5.11 22:30-22:50 例会地点:微信群语音 ...
- 仅当使用了列列表并且 IDENTITY_INSERT 为 ON 时,才能为表'TableName'中的标识列指定显式值
当某表的一个列为自动增长列,是无法直接通过insert语句向给字段写入指定值,解决方法: SET IDENTITY_INSERT TABLE_NAME ON; INSERT INTO TABLE_NA ...
- http请求的header的一个小细节
今天前后端联调的时候无论如何后端都搜不到前端的token,以为是公司全局网关拦截了token,最后发现也不是,最终在无意之中发现http请求的header的key不能带有下划线,比如app_token ...
- MyBatis(十一):Mybatis 动态SQL语句完成多条件查询
之前文章中对in的用法做过讲解:<MyBatis(四):mybatis中使用in查询时的注意事项> 实际上对于多个参数的用法也是这是注意的: 多参&if判空&List集合判 ...
- 高通qxdm抓取sensor的log【学习笔记】
高通qxdm抓取sensor的log 打开qxdm,打开设置界面,去掉其他无关的log,打开Log packets .Message packets的SNS的log 之后需要把端口打开,把端口打开之后 ...
- Cookie的Secure属性和HttpOnly属性
基于安全的考虑,需要给cookie加上Secure和HttpOnly属性,HttpOnly比较好理解,设置HttpOnly=true的cookie不能被js获取到,无法用document.cookie ...
- mysql 排序长度限制之max_length_for_sort_data以及mysql两种排序算法
SET max_length_for_sort_data = 1024 SHOW VARIABLES LIKE '%max_length_for_sort_data%'; 查询:SELECT * FR ...
- JVM线程状态Running、Sleeping、Wait、Park、Monitor
1,使用JVisualVM时,打开Threads监控,我们可以发现Java的线程状态有以下几种: 2,JVM线程状态: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_W ...
- Docker运行图形化程序
原理 Docker支持图形化程序,是利用Linux的X11技术. 相关文章 如何在Docker容器中启动D-Bus 引文详情 如何在Docker容器中启动D-Bus 翻译自 https://georg ...