虽然我们前面已经介绍完了ESFramework开发所需掌握的各种基础设施,但是还不够。想要更好地利用ESFramework这一利器,有些背景知识是我们必须要理解的。就像本文介绍的心跳机制,在严峻的Internet条件下,是通信系统中不可或缺的机制之一。 在Internet上采用TCP进行通信的系统,都会遇到一个令人头疼的问题,就是“掉线”。而“TCP掉线”这个问题远比我们通常所能想象的要复杂的多 —— 网络拓扑纷繁复杂、而从始节点A到终节点B之间可能要经过N多的交换机、路由器、防火墙等等硬件设备,每个硬件设备的相关设定也不统一,再加上网络中可能出现的拥塞、延迟等,使得我们在编程时,处理掉线也非常棘手。 一.从程序的角度看待TCP掉线 TCP掉线的原因多种多样、不一而足,比如,客人的电脑突然断电、OS崩溃、路由器重启、网线接触不良、因为P2P下载软件而导致网络资源短缺、Internet网络的不稳定等等,但是从程序的角度来说,我们可以总结为两种情况:程序能立即感知的掉线和程序不能立即感知的掉线。 1. 程序能立即感知的掉线 也就是说客户端一掉线,服务器端的某个读写对应的TCP连接的线程就会抛出异常,这种情况相对容易处理。而ESFramework针对这种情况,会触发IUserManager的SomeOneDisconnected事件,来通知我们的应用程序。       ///<summary>   /// 客户端连接被关闭时,将触发此事件。不要远程预定该事件。   ///</summary>   event CbGeneric<UserData ,DisconnectedType> SomeOneDisconnected;  2. 程序不能立即感知的掉线 我们都知道,TCP连接的建立,需要经过三次握手;而TCP连接的断开,需要经过四次挥手。掉线通常没什么大不了的,掉就掉了呗,只要四次挥手顺利完成后,服务器和客户端分别做一些善后处理就可以。

麻烦的事情在于,连接在没有机会完成4次挥手时已经断开了(比如当客人的电脑系统死机,或客人电脑与服务器之间的某处物理网线断开),而服务端以为客户端还正常在线,而客户端也自以为还正常在线。这种程序对现实状态的错误判断有可能引发诸多悲剧。比如,在此情况下,客户端发一个指令给服务器,服务器因为没有收到而一直处于等待指令的状态;而客户端了,以为服务器已经收到了,也就一直处于等待服务端回复的状态。如果程序的其它部分需要依据当前的状态来做后续的操作,那就可能会出问题,因为程序对当前连接状态的判断是错误的。

毫无疑问,这种对连接状态错误的判断所持续的时间越久,带来可能的危害就越大。当然,如果我们不做任何额外的处理措施,服务器到最后也能感受到客户端的掉线,但是,这个时间可能已经过去了几分钟甚至几十分钟。对于大多数应用来说,这是不可忍受的。 所以,针对这种不能立即感知掉线的情况,我们要做的补救措施,就是帮助程序尽快地获知tcp连接已断开的信息。

首先,我们可以在Socket上通过Socket.IOControl方法设置KeepAliveValues,来控制底层TCP的保活机制,比如,设定2秒钟检测一次,超过10秒检测失败时抛出异常。  byte[] inOptionValues = FillKeepAliveStruct(1, 10000, 2000); socket.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);

ESFramework底层已经进行了如此处理。据我们的经验,这种设定可以解决一部分问题,但是仍然会有一些连接在断开后,远远超过10秒才被感知掉。所以,这个补救措施还是远远不够的。我们还需要在应用层加入我们自己的TCP连接状态检测机制,这种机制就是通常所说的“心跳”。 二."心跳"机制 心跳机制的原理很简单:客户端每隔N秒向服务端发送一个心跳消息,服务端收到心跳消息后,回复同样的心跳消息给客户端。如果服务端或客户端在M秒(M>N)内都没有收到包括心跳消息在内的任何消息,即心跳超时,我们就认为目标TCP连接已经断开了。

由于不同的应用程序对感知TCP掉线的灵敏度不一样,所以,N和M的值就可以设定的不一样。灵敏度要求越高,N和M就要越小;灵敏度要求越低,N和M就可以越大。而要求灵敏度越高,也是有代价的,那就是需要更频繁地发送心跳消息,如果有几千个连接同时频繁地发送心跳消息,那么其所消耗的资源也是不能忽略的。

当然,网络环境(如延迟的大小)的好坏,也对会对N和M的值的设定产生影响,比如,网络延迟较大,那么N与M之间的差值也应该越大(比如,M是N的3倍)。否则,可能会产生误判 -- 即TCP连接没有断开,只是因为网络延迟大才及时没收到心跳消息,我们却认为连接已经断开了。 ESFramework内置了心跳机制: 在服务端,可通过IRapidServerEngine的HeartbeatTimeoutInSecs属性来设置上面描述的M值。 在客户端,则通过IRapidPassiveEngine的HeartBeatSpanInSecs属性设置N值。 当心跳超时时,服务端会触发IUserManager的SomeOneTimeOuted事件,来通知我们的应用程序。     三.必须关闭掉线的TCP连接

无论是普通掉线(立即感知)还是心跳超时掉线(非立即感知),都需要关闭对应的TCP连接以释放系统资源。ESFramework将会自动帮我们关闭掉线的TCP连接。 另外要提醒一点,当TCP连接超时掉线时,服务端会引擎首先会触发IUserManager的SomeOneTimeOuted事件,接着再触发IUserManager的SomeOneDisconnected事件。 四.UDP与"心跳"

前面介绍的都是关于TCP的掉线的问题,下面我们看看UDP。 由于UDP是无连接的协议,所以,当我们在使用ESFramework的UDP引擎的时候,几乎肯定是需要配备心跳机制的,使用心跳消息确认客户端还在线,以保证服务端不会过早释放对应的Session或长期保留已失效的Session。      在ESFramework 开发手册(04) -- 可靠的P2P 一文中介绍的P2P通道如果是基于UDP的,则ESPlus内部也启动了心跳机制,以保证在基于UDP的P2P通道断开时,ESPlus能尽快感知,并关闭对应的P2P通道。 五.关闭心跳机制 比如,在LAN中进行通信的分布式系统,由于网络延迟和意外掉线的几率微乎其微,所以,可以考虑关闭心跳机制。再比如,当我们断点调试客户端程序时,由于断点时间太久,服务端会判断为客户端已经心跳超时掉线了,在这种情况下,也可以关闭心跳机制。那么如何关闭心跳机制了?可以这样做: 将IRapidPassiveEngine的HeartBeatSpanInSecs属性设置为0。这样客户端就不会发送定时的心跳消息了。 将IRapidServerEngine的HeartbeatTimeoutInSecs属性设置为小于等于0。这表示服务端将不再做心跳超时检查。

六.客户端如何快速感知自己掉线? 在某些客户端电脑上,比如拔掉网线,或断开wifi,程序可能需要几秒到几分钟才能感知到自己掉线,不同的电脑这个感受的时间不一样。那么如何才能让客户端尽可能快地得到掉线通知了?
可以利用socket写超时的机制,像下面这样做:
(1)将Socket发送缓冲区的大小设置为0。       对应IRapidPassiveEngine的Advanced属性的WriteTimeoutInSecs属性。
(2)设置写超时为一个较小的值,如30秒。      对应IRapidPassiveEngine的Advanced属性的SocketSendBuffSize属性。
这样,结合上面的心跳发送机制(如每隔5秒发送一个心跳),则当网络断开后,在发送心跳消息,最多再过30秒,程序就会得到掉线通知了。

http://blog.oraycn.com/ESFramework_07.aspx

ESFramework 开发手册(07) -- 掉线与心跳机制(转)的更多相关文章

  1. 判定生死的心跳机制 --ESFramework 4.0 快速上手(07)

    在Internet上采用TCP进行通信的系统,都会遇到一个令人头疼的问题,就是"掉线".而"TCP掉线"这个问题远比我们通常所能想象的要复杂的多 -- 网络拓扑 ...

  2. [心跳] 使用心跳机制实现CS架构下多客户端的在线状态实时更新以及掉线自动重连

    此文讲述的内容是一个实际项目开发中的一部分内容,笔者将亲身经历写成文章. [背景] 现 需要实现这样的功能:有多个客户端连着同一个服务器.服务器和客户端之间需要“互相”知道彼此的连接状态.比如在某一时 ...

  3. 使用心跳机制实现CS架构下多客户端的在线状态实时更新以及掉线自动重连

    此文讲述的内容是一个实际项目开发中的一部分内容,笔者将亲身经历写成文章. [背景] 现需要实现这样的功能:有多个客户端连着同一个服务器.服务器和客户端之间需要“互相”知道彼此的连接状态.比如在某一时刻 ...

  4. TCP长连接与短连接、心跳机制

    1. TCP连接 当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立是需要三次 ...

  5. 基于netty实现的长连接,心跳机制及重连机制

    技术:maven3.0.5 + netty4.1.33 + jdk1.8   概述 Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速 ...

  6. [转]Android TCP长连接 心跳机制及实现

    背景知识 智能手机上的长连接心跳和在Internet上的长连接心跳有什么不同 Android系统的推送和iOS的推送有什么区别 几种推送的实现方式 协议 1XMPP简介 2 MQTT简介 3移动端消息 ...

  7. Netty学习篇④-心跳机制及断线重连

    心跳检测 前言 客户端和服务端的连接属于socket连接,也属于长连接,往往会存在客户端在连接了服务端之后就没有任何操作了,但还是占用了一个连接:当越来越多类似的客户端出现就会浪费很多连接,netty ...

  8. 《即时消息技术剖析与实战》学习笔记8——IM系统如何保证长连接的可用性:心跳机制

    假设有以下突发意外情况: 用户进入信号不好的地方,手机没有网络信号了 上网的路由器突然掉线了 这个时候,比如微信发消息,消息就会转圈圈,甚至变成红色叹号-- 上面情况都会导致"长连接&quo ...

  9. “嘭、嘭、嘭”---C/S架构下的心跳机制

    本人想使用AU3开发多客户端.一服务端.需要使用到心跳机制,即 在线状态实时更新以及掉线自动重连. 搜索网络发现没有人用AU3写心跳机制. 下面是一篇转帖(原文地址:http://www.cnblog ...

随机推荐

  1. 如何关闭android studio开发环境自动保存

    使用DW习惯了现在转到学习开发android,请问怎样关闭android studio的自动保存功能,然后按ctrl+s进行保存,因为有时候代码不想让其保存,他也自动保存了. File -> S ...

  2. Apache+windows server2008 外网访问配置

    之前在一个服务器上部署一个apache网站,在局域网内都可以访问,但是外网始终访问不了,经常多次谷歌,把解决方案总结出来. 下面就默认部署apache自带的网站.系统:windows server20 ...

  3. 第四题(迅雷笔试题):编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。

    #include <iostream> #include <stdlib.h> #include <pthread.h> using namespace std; ...

  4. TCP/IP详细解释--TCP/IP可靠的原则 推拉窗 拥塞窗口

    TCP和UDP在同一水平---传输层.但TCP和UDP最不一样的地方.TCP它提供了一个可靠的数据传输服务,TCP是面向连接的,那.使用TCP两台主机通过第一通信"拨打电话"这个过 ...

  5. 使用ROW_NUMBER()查询:列名 'RowNumber' 无效。

    原文:使用ROW_NUMBER()查询:列名 'RowNumber' 无效. 使用ROW_NUMBER()方法查询结果集:语句如下:   select ROW_NUMBER() OVER(ORDER ...

  6. 一款新型的智能家居WiFi选择方案——SimpleWiFi在无线智能家居中的应用

    一款新型的智能家居WiFi选择方案——SimpleWiFi在无线智能家居中的应用 先上图:     随着科学技术的不断发展,局域网也正逐渐向无线化,多网合一的方向发展,在这个多网合一快速发展过程中,带 ...

  7. Linux源文件夹结构呈现

    1.arch文件夹: - 相关的存储在不同平台上的代码,每个平台都采用了不同的文件夹来区分. ******Alpha平台 ******Arm平台 ******Arv32平台 ******X86平台 2 ...

  8. 【VB/.NET】Converting VB6 to VB.NET 【Part II】【之四】

    第四部分 原文 DLLs, DAO, RDO, ADO, and AD.NET; the History of VB DBs In the early versions of VB, there we ...

  9. HDU1789Doing Homework again(贪婪)

    HDU1789Doing Homework again(贪心) 题目链接 题目大意:给你n们作业的最后期限和过了这个期限没做须要扣的分数.问如何安排能够使得扣分最少. 解题思路:贪心,将扣分多的作业排 ...

  10. Kafka 高性能吞吐揭秘

    Kafka 高性能吞吐揭秘   Kafka作为时下最流行的开源消息系统,被广泛地应用在数据缓冲.异步通信.汇集日志.系统解耦等方面.相比较于RocketMQ等其他常见消息系统,Kafka在保障了大部分 ...