一个简易的心跳包 C# Socket (上)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个简易的心跳包 C# Socket (上)相关的知识,希望对你有一定的参考价值。

参考技术A 貌似 都注释上了没啥好说的, NowTimeSpan => Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds); 这个就是一个只读的写法,每次读取都会读现在的时间与默认的时间差距秒,从而去计算心跳包的秒数
InitMax()就是初始化上限数值 超时次数 超时上限
UpdateHeat()就是更新心跳包的 重新赋值当前与默认时间的差距秒数, 如果过段时间不更新不更新当前持有的秒数也不会更新 在CheckHeat()检测超过限定的超时时间MaxLostTime 就是增加一次Lostcount超时次数

KGHeartBeatManage<T,R>:IDisposable where R:KGHeartBeat 这里的T就是你们定义的每个会话管理类,R就是指定要继承KGHeartBeat 的

初始化事件 InitTimerEvent(第一个委托就是发送事件,第二个委托就是 每个心跳包如果超时就会回调回来,每隔多少毫秒触发一次检测,每隔多少毫秒发送心跳包)
然后StartTimer()就可以开始触发了
这边定时器那里加了个每次都会检测ConnectDic字典里面储存的心跳包,如果超过最大上限超时次数就会回调 KGHeartBeatManage里面的第二个委托,告诉他这个连接已经超时,

AddConnectDic(对应的会话管理类,指定超时时间,超时次数)这里会创建出对应的KGHeartBeat数据里存在字典里面,每个会话管理对应一个心跳包数据
RemoveConnectDic(T obj) 这里是移除字典里面 该会话管理对应的心跳包

因为会有多线程触发的问题这里用了lock互斥锁,排队来,

https://github.com/LKaiGuo/KGScriptGenerator 喜欢的给我点个星星啊
u3d萌新QQ群844087555 欢迎进来灌水=。=

Socket心跳包机制总结

参考技术A tcp的断线检测,分为两种:

① 利用tcp自带的keep –alive机制

② 自己组建心跳包的方式向对端发送

通过Keep-alive机制对tcp的连接保持,也就是Tcp的心跳包,见MSDN:

If keep-alive is enabled for a TCP socket with SO_KEEPALIVE, then the default TCP settings are used for the keep-alive timeout and interval unless these values have been changed by calling the WSAIoctl function with the SIO_KEEPALIVE_VALS option. The default settings when a TCP socket is initialized sets the keep-alive timeout to 2 hours and the keep-alive interval to 1 second.

也就是说协议栈会在2小时后发送向对端发送请求包。默认情况下,此Keep-alive机制是关闭的。

Keep-alive默认下是关闭的,也就是本端与对端是除非程序主动send,是不会发送数据包(心跳包),既是,处理本端与对端的系统里的socket状态是不会变化,这里,如果对端当机(或者网线断掉),本端是无法知道对端socket已经关闭,所以本端的socket会一直的存在。

通过实验发现,客户端网线拔掉之后,此时服务端的连接依然存在。

所以,tcp只是数据的发送与接收,包括握手,断开以及rst,time_wait,close_wait 等等。

心跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。

在TCP的机制里面,本身是存在有心跳包的机制的,也就是TCP的选项:SO_KEEPALIVE。系统默认是设置的2小时的心跳频率。但是它检查不到机器断电、网线拔出、防火墙这些断线。而且逻辑层处理断线可能也不是那么好处理。一般,如果只是用于保活还是可以的。

心跳包一般来说都是在逻辑层发送空的echo包来实现的。下一个定时器,在一定时间间隔下发送一个空包给客户端,然后客户端反馈一个同样的空包回来,服务器如果在一定时间内收不到客户端发送过来的反馈包,那就只有认定说掉线了。 其实,要判定掉线,只需要send或者recv一下,如果结果为零,则为掉线。

但是,在长连接下,有可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉
。在这个时候,就需要我们的心跳包了,用于维持长连接,保活。

在获知了断线之后,服务器逻辑可能需要做一些事情,比如断线后的数据清理呀,重新连接呀……当然,这个自然是要由逻辑层根据需求去做了。

总的来说,心跳包主要也就是用于长连接的保活和断线处理。一般的应用下,判定时间在30-40秒比较不错。如果实在要求高,那就在6-9秒。

1、 客户端每隔一个时间间隔发生一个探测包给服务器
2、 客户端发包时启动一个超时定时器
3、 服务器端接收到检测包,应该回应一个包
4、 如果客户机收到服务器的应答包,则说明服务器正常,删除超时定时器
5、 如果客户端的超时定时器超时,依然没有收到应答包,则说明服务器挂了

以上是关于一个简易的心跳包 C# Socket (上)的主要内容,如果未能解决你的问题,请参考以下文章

Socket心跳包机制总结

c# c/s 之间如何做心跳检测

Socket心跳包机制

hpsocket默认心跳

socket心跳包

心跳包-注册包-多路socket