客户端会周期性的向服务器发心跳包,如果服务器端在一定的时间内没有收到心跳包或者是正常的调用操作就认为该客户端掉线了。当一个客户端的心跳过来的时候,服务器端具体该如何做呢?如果服务器端维护一个在线的列表,该如何来触发这个删除的操作呢?

解决方案 »

  1.   

    http://blog.csdn.net/QGJava/archive/2010/07/19/5745776.aspx
      

  2.   

    http://topic.csdn.net/u/20100712/23/f327aa8b-3116-4a78-8dd7-9f4c0416b9dd.html
      

  3.   


    当一个客户端的心跳过来的时候,服务器端具体该如何做呢?客户端在线的flag置位,假如你有这样的flag的话如果服务器端维护一个在线的列表,该如何来触发这个删除的操作呢?如果服务端没收到某个客户端的心跳包,考虑给一个超时次数计数,比如客户端3次超时,则认为该客户端已经掉线,可删除之..., 如果仅仅一次收不到就认为掉线是不合理的.
      

  4.   


    其实这应该反过来看你的问题。你是否首先在服务器数据库中有一个“会话”对象?如果有,那么它应该记录“最后一次活跃时间”信息。(当然,这应该是UTC时间,不过这是另外的话题)接下来,客户端任何操作,如果它需要访问访问会话对象,例如以便知道是哪一个用户绑定(登录)到这个会话上,或者需要查询这个会话有没有推送广告,之类的,此时其实都可以更新这个“最后一次活跃时间”。也就是说,并不是必须通过心跳消息,而是几乎任何消息都可以用来更新会话的活跃状态。心跳消息实际上只是在客户端什么都不做时,发一个告诉后台“我什么都不做”的消息给服务器。这样说我相信lz就会更明白心跳消息的作用了。关于删除会话记录,其实如果你的硬盘不是很缺乏控件,完全可以不删除。保存的记录其实关联了许多日志信息,删除了其实丢失了一些数据。当然如果你的业务很小,或者数据库很小,可以考虑几天删除一次。
      

  5.   

    http://www.cnblogs.com/xugang/archive/2008/04/15/1154689.html
    关于Socket通信服务的心跳包(转)
      

  6.   

    sorry,把“之内”打字写成“之前”了。
      

  7.   

    从服务器端的功能来说,没有什么不是基于数据库的。所以架构的描述简单来说就是基于数据库。但是实际深入、实现、优化,并不是纠结于数据库。例如根据成本不同而使用不同类型的缓存,甚至使用大规模的存储卡来做数据库缓存。实际上我所说的数据库,不是指某一种关系数据库产品。从文本文件,xml文件、excel文件、word文件,到云服务、我们的电脑的显卡缓冲区,都可以作为我所说的数据库。我只是用来说明对象需要持久化、高速查询。而没有指任何关系数据库产品。你所用的数据库产品有没有所需要的性能,不足以左右这里对架构的说明。
      

  8.   

    我们的做法:
    每个通过认证服务器注册的客户端在服务器都会与硬件信息绑定分配一个唯一标识,
    我们把这个唯一标识称为"票根"或"凭证",
    每个客户端请求一个新的站点之前,先向认证服务器请求一个"票头",
    目标站点收到"票头"(也就是客户跳转成功)后,立即请求认证服务器销毁"票头",
    这样可以用最低的代价获得满足一般商业应用的安全性要求,网路上没有任何关于客户信息的明文传递;而在线信号只需要对应"票根"发送ture,服务器更新对应行的LastTime=GETDATE()就可以了,
    同时心跳包的策略要考虑利用用户的主动提交,避免不必要的重复执行
      

  9.   

     看看这个吧~ 在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(一)----基础类库部分
     http://blog.csdn.net/yangjundeng/archive/2005/03/17/321920.aspx 
     不仅有标准的模块,而且帮你把结构都搞定了。
     
      

  10.   


    我现在感到困惑的就是这里。如果给flag置为真后,客户端不再发数据过来了。它的flag由谁去改成假呢?
      

  11.   

    1.维护一个在线客户端列表,你要检测客户端,必然要客户端主动登陆,每当遇到客户端登陆时候,根据心跳包信息把这个客户端标识添加进一个在线列表.这个列表比如可以用一个字典来做,key是客户端标识,value是收到心跳的时间信息.这样当客户端登陆后,在线字典先找这个key是否存在,存在就将value值更新,不存在就添加元素.
    2.可以做一个专用线程然后固定时间检查在线列表,通过对比每一个元素的value,也就是时间来判断是否已经超时连接了.因为心跳都是有固定时间间隔的.
      

  12.   

    虽然我非常不赞成使用基于c-s的关系数据库来做c-s应用系统(我认为这种应用程序根本不是c-s的),不过如果你使用这种结构,那么其实我的假设是:关系数据库系统不应该暴露任何数据库表结构,客户端只能通过存储过程访问数据库系统。当然这样做并不是为了所谓性能问题,但是我想很多程序员的顾虑可以解除了,因为你可以专心考虑数据库存储过程中如何执行多个数据库操作行为的“效率”,而不用顾及客户端多次访问数据库系统的“效率”问题。
      

  13.   

    呵呵,不过我做的服务器程序至今还没有用c-s数据库做客户端接口的,而是通过tcp、udp、http、namedpipe等方式来访问的专用数据库系统。所以,我的设计许多地方很自然会更自由一些。
      

  14.   

    即使没有心跳包,超时也很重要,这是保证通讯稳定的最前提。超时是保证命令收发正常,心跳是保证对方一直跟你有连接。你的心跳包用在什么业务我不清楚,我前面提到的那个方法是我在生产环境中实际遇到的问题和我的一个解决方案。如果你是做winform开发写的数据通讯程序用那个模型没问题。
    如果你是做web,或者需要数据库,那么你甚至不需要心跳包,可以参考下QQ服务器模型。那么多用户总不可能是服务器一直接心跳吧?当然具体QQ服务器肯定算法和结构都有优化,而且架构比你这个要复杂,但是简单来说可以用如下方案:client登陆,server收到信息进行蒲记,加入数据库中,然后所有要跟目标client通讯的其他client登陆后获取数据库中信息,看目标client是否登陆,已登陆可进行通讯。如果刚开始两个client通讯没问题,后来其中一方断开连接怎么办?这个时候超时就有用了,比如判断3次超时重发未成功,就认为对方短了,这时候你给服务器发送一个信息,server收到这个信息后在登陆蒲记表里删除相应的client。同时,为了优化,client正常关系时候要发送指令告诉server,让server把它从登陆蒲记表里删除。最后一点,你会问,两个互通的client都断了怎么办?你可以不管,应为这种情况下,没有人用到这两个client,所以他俩是否连接不重要,如果有第三方连接,就又回到前面双方互联一方断开的分析了.当然,还有很多优化算法和解决方案,就看你怎么设计了.
      

  15.   

    你要明白你这个需求获得的是很临时的东西,很临时的东西放哪里存取最快?内存中肯定比数据库里要快.要是硬要用数据库,那很明确的说,你怎么操作都要读写数据库一次,这一次的时间,对于CPU来说,是非常漫长的....
      

  16.   

    asp.net不懂你问服务器端怎样维护客户端的状态,其实也可以采用心跳的方式,每当有客户端心跳一次,那服务器端的计数器就加1,然后服务器有自己的心跳,每个一定时间就心跳一次,把计数器减1,直到计数器一归零,就销毁对象
      

  17.   

    搞个在线有这么复杂吗?心跳就是为了让服务器和客户端的之间的连接保持不断,别的事你管他干嘛当网络断开的时候,Socket自然会抛异常,这个时候你再从在线表中删除这个Socket不是很省事?
      

  18.   


    可以反过来思考,服务器主动发消息给客户端,如果失败,就认为掉线:
    try{
      SendToClient(client1);
    }
    catch
    {
       从在线表中删除client1
    }
      

  19.   

    心跳 -- Heart-beat 机制通常用来进行通信连接的保活测试。感觉楼上你们把这个问题复杂化了,其实非常简单。heart-beat通常根据场景有两种方式:1、单方面的heart-beat通知另外一方己方在线;2、双方的heart-beat/heart-beat ack.C/S架构下:
    1、如果只是需要C通知S己方在线,那么就定时的让C发送heart给S。
    2、S端根据使用的IO模型来确定是否C掉线了。比如,如果使用的IOCP模型,那么就通过对GetCompeletionStatus结合一定的超时机制来判断是否C还在线,可以使用GetTickCount来检查超时的时间,如果超时越过门限,则close这个C就行了。
    3、如果是其他的IO模型,那么参考同样的道理,你的CClientContext类里面需要记录一个heart的最后时间ticket即可。通用的做法是建立一个housekeeping thread来遍历检查各个客户端的状态,如果超时越过门限就closesocket and removelicent即可。其实就这么简单明了,别简单问题复杂化。