iocp网络通信之如何判断客户端连接断开

来源:互联网 发布:js获取当前页面内容 编辑:程序博客网 时间:2024/05/21 10:35

 

BOOL r = ::GetQueuedCompletionStatus(hCompletionPort, &dwBytesTransferred, (LPDWORD)&hCompletionSocket, (LPWSAOVERLAPPED *) &lpOvlpEx, INFINITE);if (hCompletionSocket== INVALID_SOCKET || lpOvlpEx == NULL){Sleep(10);continue;}if (!r){proxy->SafeClose(lpOvlpEx);TRACE("GetQueuedCompletionStatus error! %d\n",hSocket);continue;}else if (dwBytesTransferred ==0){proxy->SafeClose(lpOvlpEx);TRACE(".....................%d..........closed & freed........\n",hSocket);continue;}


上面的GetQueuedCompletionStatus是接收IOCP通知的主要函数,通过dwBytesTransferred、hCompletionSocket、lpOvlpEx以及返回值r即可判断出客户端是否关闭。

但是,GetQueuedCompletionStatus不能得出网络是否异常了,比如客户端拔网线,比如突然重启,这些是无法捕获的。这是由于TCP协议本身的问题,其实细想一下,客户端还没有把数据发送缓冲区时系统就崩溃了,这种情况下肯定无法捕获的,只能通过应用协议来判断了。常用的解决方法三种:

  1. 定时心跳包,超时没收到回应,就认为客户端就是断开了。
  2. 通过SO_KEEPALIVE来判断,默认是2小时进行一次检测,自己也可以设置检测间隔,但会影响其它系统所有正在使用的Socket,慎用
  3. 通过SIO_KEEPALIVE_VALS,该选项不同于SO_KEEPALIVE 机制的就是它是针对单个连接的,对系统其他的Sokcet并不影响。