用户异常掉线检测
                                 David.Zhu  2005/6/1
   目前主要有三种方法来实现用户掉线检测:SO_KEEPALIVE ,SIO_KEEPALIVE_VALS 和Heart-Beat线程。
下面我就上面的三种方法来做一下介绍。
(1)SO_KEEPALIVE 机制 
        这是socket库提供的功能,设置接口是setsockopt API:
   BOOL  bSet=TRUE;
   setsockopt(hSocket,SOL_SOCKET,SO_KEEPALIVE,(const char*)&bSet,sizeof(BOOL));

根据MSDN的文档,如果为socket设置了KEEPALIVE选项,TCP/IP栈在检测到对方掉线后,
   任何在该socket上进行的调用(发送/接受调用)就会立刻返回,错误号是WSAENETRESET ;
   同时,此后的任何在该socket句柄的调用会立刻失败,并返回WSAENOTCONN错误。

该机制的缺点也很明显:
         默认设置是空闲2小时才发送一个“保持存活探测分节”,不能保证实时检测!
   当然也可以修改时间间隔参数,但是会影响到所有打开此选项的套接口!
         关联了完成端口的socket可能会忽略掉该套接字选项。

(2)SIO_KEEPALIVE_VALS 机制 
         这是从彭博兄那里学到一个机制拉,设置接口是WSAIoctl API:
     DWORD dwError = 0L ;
     tcp_keepalive sKA_Settings = {0}, sReturned = {0} ;
     sKA_Settings.onoff = 1 ;
     sKA_Settings.keepalivetime = 5500 ; // Keep Alive in 5.5 sec.
     sKA_Settings.keepaliveinterval = 3000 ; // Resend if No-Reply 
     if (WSAIoctl(skNewConnection, SIO_KEEPALIVE_VALS, &sKA_Settings,
          sizeof(sKA_Settings), &sReturned, sizeof(sReturned), &dwBytes,
          NULL, NULL) != 0)
     {
           dwError = WSAGetLastError() ;
     }
     实现时需要添加tcp_keepalive and SIO_KEEPALIVE_VALS的定义文件MSTCPiP.h 
     该选项不同于SO_KEEPALIVE 机制的就是它是针对单个连接的,对系统其他的套接
     口并不影响。
        针对完成端口的socket,设置了SIO_KEEPALIVE_VALS后,激活包由TCP STACK来负责。
     当网络连接断开后,TCP STACK并不主动告诉上层的应用程序,但是当下一次RECV或者SEND操作
     进行后,马上就会返回错误告诉上层这个连接已经断开了.如果检测到断开的时候,在这个连接
     上有正在PENDING的IO操作,则马上会失败返回.

该机制的缺点:
             不通用啦。MS的API只能用于Windows拉。不过,呵呵用彭博兄的评论就是:
     优雅一些^_^.
    
(3)Heart-Beat线程
        没说的。自己写一个后台线程,实现Heart-Beat包,客户端受到该包后,立刻返回相应的反馈  包。

该方法的好处是通用,但缺点就是会改变现有的通讯协议!

有开发网络应用经历的人都知道,网络中的接收和发送数据都是使用WINDOWS中的SOCKET进行实现。但是如果此套接字已经断开,那发送数据和接收数据的时候就一定会有问题。可是如何判断这个套接字是否还可以使用呢?

  有人一定想到使用Send函数中的返回结果来进行判断。如果返回的长度和自己发送出去的长度一致,那就说明这个套接字是可用的,否则此套接字一定出现了问题。但是我们并不是无时无刻的发送数据呀。如何解决呢?

  其实TCP中已经为我们实现了一个叫做心跳的机制。如果你设置了心跳,那TCP就会在一定的时间(比如你设置的是3秒钟)内发送你设置的次数的心跳(比如说2次),并且此信息不会影响你自己定义的协议。

  在VC中实现心跳的例子很多,可是在DLEPHI中一直没有相应的代码。下面我是我使用DELPHI编写的关于心跳的代码(以IOCP为例),希望对大家有帮助。

定义心跳常量

const
  IOC_IN               =$80000000;
  IOC_VENDOR           =$18000000;
  IOC_out              =$40000000;
  SIO_KEEPALIVE_VALS   =IOC_IN or IOC_VENDOR or 4;

var

inKeepAlive,OutKeepAlive:TTCP_KEEPALIVE;

实现代码是在Acceptsc:= WSAAccept(Listensc, nil, nil, nil, 0);代码的后面加入:

opt:=1;
      if setsockopt(Acceptsc,SOL_SOCKET,SO_KEEPALIVE,@opt,sizeof(opt))=SOCKET_ERROR then
      begin
        closesocket(Acceptsc);
      end;
      inKeepAlive.onoff:=1;
      //设置3秒钟时间间隔

  inKeepAlive.keepalivetime:=3000;

//设置每3秒中发送1次的心跳
      inKeepAlive.keepaliveinterval:=1;
      insize:=sizeof(TTCP_KEEPALIVE);
      outsize:=sizeof(TTCP_KEEPALIVE);
      if WSAIoctl(Accept,SIO_KEEPALIVE_VALS,@inKeepAlive,insize,@outKeepAlive,outsize,@outByte,nil,nil)=SOCKET_ERROR then
      begin
        closesocket(Acceptsc);
      end;

如果加入以上的代码以后,系统会每3秒中加入一次的心跳。并且如果客户端断线以后(网线断),函数GetQueuedCompletionStatus会返回FALSE。

if (GetQueuedCompletionStatus(CompletionPort, BytesTransferred,DWORD(PerHandleData), POverlapped(PerIoData), INFINITE) = False) then
        begin
           //在这里处理客户端断线信息。

   continue;
        end;

以上就是我使用心跳的方法,此方法我已经在我的网络游戏中使用。情况稳定!

SIO_KEEPALIVE_VALS 用户异常掉线检测相关推荐

  1. 微信亿级用户异常检测框架的设计与实践

    微信亿级用户异常检测框架的设计与实践 参考文章: (1)微信亿级用户异常检测框架的设计与实践 (2)https://www.cnblogs.com/qcloud1001/p/8351385.html ...

  2. 异常分发(用户异常)

    文章目录 内容回顾: 用户异常的处理流程: 总结 内容回顾: 异常如果发送在内核层,处理起来比较简单,因为异常处理函数也在0环,不用切换堆栈,但是如果异常发生在3环,就意味着必须要切换堆栈,回到3环执 ...

  3. Windows异常学习笔记(二)—— 内核异常处理流程用户异常的分发

    Windows异常学习笔记(二)-- 内核异常处理流程&用户异常分发 用户层与内核层异常 内核异常 分析 KiDispatchException 分析 RtlDispatchException ...

  4. 手把手教学电瓶车进电梯检测、多类别车辆追踪、异常行为检测产业级应用

    近日,媒体接连报道电动车起火爆炸造成严重人员伤亡的新闻,针对该问题,社区物业明令禁止电瓶车入户,但是依然有人忽视这个问题严重性.目前,AI应用已经可以有效地预防此类问题,在进入电梯的时候就可以采取报警 ...

  5. php if终止,php判断用户是否掉线及关闭网页的方法分享

    要实现判断用户已掉线并关闭网页,主要用到方法connection_status 和 connection_aborted. 通过一个例子,来了解下它们的用法: echo str_repeat(&quo ...

  6. 异常行为检测算法_检测异常行为的异常或异常类型算法

    异常行为检测算法 Anomaly detection is a critical problem that has been researched within diverse research ar ...

  7. R异常数据检测及处理方法

    R异常数据检测及处理方法 数据中的异常值可能会影响或者干扰模型的准确性以及可靠性,如果我们不正确地检测和处理它们,尤其是在回归模型中异常值对模型的干扰比较大,即回归模型对异常值敏感. 为什么异常点检测 ...

  8. Java 创建用户异常类、将异常一直向上抛、 throw和throws的区别

    Java 创建用户异常类.将异常一直向上抛. throw和throws的区别 参考文章: (1)Java 创建用户异常类.将异常一直向上抛. throw和throws的区别 (2)https://ww ...

  9. boost::test模块自定义用户异常转换器注册表的单元测试

    boost::test模块自定义用户异常转换器注册表的单元测试 实现功能 C++实现代码 实现功能 boost::test模块自定义用户异常转换器注册表的单元测试 C++实现代码 #include & ...

最新文章

  1. Dotfuscator代码混淆工具的使用
  2. Hibernate 的 session.load()使用方法
  3. linux内核杂记(14)-Linux kernel release 5.x(1)
  4. 【Linux】一步一步学Linux——dpkg命令(269)
  5. springboot问题Description Resource Path Location Type Java compiler level does not match the version o
  6. 一个亿万富翁和一个陌生人的换钱计划
  7. python入门html_python-html入门
  8. 第 17 章 命令模式
  9. vivado ip xdc 和user xdc 编译顺序
  10. PotPlayer 禁止更新
  11. C语言程序设计第三版微课版,C语言程序设计(第3版 微课版)
  12. 跨进程 API hook
  13. JAVA计算机毕业设计学生请假管理系统Mybatis+系统+数据库+调试部署
  14. libaio.so.1 is needed by MySQL-server-5.5.48-1.linux2.6.i386
  15. 阿里云漏洞修复 RHSA-2019:0109-Important: perl secur
  16. SylixOS之OK6410开发板系统烧写
  17. UG NX二次开发-外部模式
  18. x86 单线并发多拨_带宽“单线多拨“倍增大法教程
  19. Python ctypes的byref和pointer区别
  20. android平台下OpenGL ES 3.0绘制圆点、直线和三角形

热门文章

  1. java group布局_Java的swing.GroupLayout布局管理器的使用方法和实例
  2. 手动推导计算AES中的s盒的输出
  3. 日期解析:2021-05-15T23:30:00+08:00
  4. 全球规模最大天文馆上海天文馆18日正式开馆,这里让你先睹为快!
  5. matlab 声源定位csdn_[转]基于TDOA声源定位算法仿真--MATLAB仿真
  6. MIMIC IV数据库安装(二)
  7. 移动端下载xls文件
  8. 随笔感悟:程序员的“孩纸们”
  9. [51nod1326]遥远的旅途
  10. 玩转PYthon,用Python绘制全球疫情变化地图(好东西,值得一看~~~)