ESFramework 开发手册(07) -- 掉线与心跳机制(转)
虽然我们前面已经介绍完了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) -- 掉线与心跳机制(转)的更多相关文章
- 判定生死的心跳机制 --ESFramework 4.0 快速上手(07)
在Internet上采用TCP进行通信的系统,都会遇到一个令人头疼的问题,就是"掉线".而"TCP掉线"这个问题远比我们通常所能想象的要复杂的多 -- 网络拓扑 ...
- [心跳] 使用心跳机制实现CS架构下多客户端的在线状态实时更新以及掉线自动重连
此文讲述的内容是一个实际项目开发中的一部分内容,笔者将亲身经历写成文章. [背景] 现 需要实现这样的功能:有多个客户端连着同一个服务器.服务器和客户端之间需要“互相”知道彼此的连接状态.比如在某一时 ...
- 使用心跳机制实现CS架构下多客户端的在线状态实时更新以及掉线自动重连
此文讲述的内容是一个实际项目开发中的一部分内容,笔者将亲身经历写成文章. [背景] 现需要实现这样的功能:有多个客户端连着同一个服务器.服务器和客户端之间需要“互相”知道彼此的连接状态.比如在某一时刻 ...
- TCP长连接与短连接、心跳机制
1. TCP连接 当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立是需要三次 ...
- 基于netty实现的长连接,心跳机制及重连机制
技术:maven3.0.5 + netty4.1.33 + jdk1.8 概述 Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速 ...
- [转]Android TCP长连接 心跳机制及实现
背景知识 智能手机上的长连接心跳和在Internet上的长连接心跳有什么不同 Android系统的推送和iOS的推送有什么区别 几种推送的实现方式 协议 1XMPP简介 2 MQTT简介 3移动端消息 ...
- Netty学习篇④-心跳机制及断线重连
心跳检测 前言 客户端和服务端的连接属于socket连接,也属于长连接,往往会存在客户端在连接了服务端之后就没有任何操作了,但还是占用了一个连接:当越来越多类似的客户端出现就会浪费很多连接,netty ...
- 《即时消息技术剖析与实战》学习笔记8——IM系统如何保证长连接的可用性:心跳机制
假设有以下突发意外情况: 用户进入信号不好的地方,手机没有网络信号了 上网的路由器突然掉线了 这个时候,比如微信发消息,消息就会转圈圈,甚至变成红色叹号-- 上面情况都会导致"长连接&quo ...
- “嘭、嘭、嘭”---C/S架构下的心跳机制
本人想使用AU3开发多客户端.一服务端.需要使用到心跳机制,即 在线状态实时更新以及掉线自动重连. 搜索网络发现没有人用AU3写心跳机制. 下面是一篇转帖(原文地址:http://www.cnblog ...
随机推荐
- 利用WinDbg找出程序崩溃的代码行号
之前碰到论坛里有几个好友,说程序不时的崩溃,什么xxoo不能read的! 如果光要是这个内存地址,估计你会疯掉~~ 所以分享一下基本的调试技巧,需要准备的工具有WinDbg + VC6.0, 下面是自 ...
- 新的方法 (New Approach)¶
第一章:简介 - ANSI Common Lisp 中文版 新的方法 (New Approach)¶ 本书的目标之一是不仅是教授 Lisp 语言,而是教授一种新的编程方法,这种方法因为有了 Lisp ...
- tar.gz文件命名和压缩解压方法
tar.gz文件命名 tar这是文件打成一个包,无压缩; gz同gzip标记的包.tar文件压缩; 所以它成为一个.tar.gz档 压缩 # tar cvfz backup.tar.gz /xxx/ ...
- JMS的样例
1.JMS是一个由AS提供的Message服务.它能接受消息产生者(Message Provider)所发出的消息,并把消息转发给消息消费者(Message Consumer).2.JMS提供2种类 ...
- iphone开发中数据持久化之——模型对象归档(二)
在Cocoa世界中,术语“归档”是指另一种形式的序列化,它可以实现对任何对象的序列化.使用对模型对象进行归档的技术可以轻松将复杂的对象写入文件,然后再从中读取它们.只要在类中实现的每个属性都是标量(如 ...
- OpenAuth.net
基于DDDLite的权限管理OpenAuth.net 1.0版正式发布 距离上一篇OpenAuth.net的文章已经有5个多月了,在这段时间里项目得到了很多朋友的认可,开源中国上面的Star数接近 ...
- DOM的event对象的属性和方法
属性/方法 类型 是否可读写 描写叙述 altKey Boolean 读写 指示是否按下alt键 bubbles Boolean 读 指示事件是否冒泡 button Intrger 读写 鼠标事件发生 ...
- poj3414(bfs)
题目链接:http://poj.org/problem?id=3414 题意:给你两个容器 A B 问是否能够经过有限的步骤倒水,得到容量为 C 的水,输出最小的步数,同时输出每一步的操作.如果不能 ...
- PPPOE 模拟环境搭建
这段时间.包含我自己測试OTT盒子 PPPOE的时候比較痛苦.要不就是在别人的位置上測试.要不就是借用PPPOE的设备,认为还是自己搭建一个PPPOE真实拨号上网的环境多好! 可是坑爹的win7找不到 ...
- codeforces#256DIV2 D题Multiplication Table
题目地址:http://codeforces.com/contest/448/problem/D 当时是依照找规律做的,规律倒是找出来了,可是非常麻烦非常麻烦. . 看到前几名的红名爷们3分钟就过了, ...