网络编程-基于IOCP的服务器中使用TCP连接时如何知道客户端已经异常断开?
基于IOCP的服务器,经常会发生客户端断开连接。由于网络经常出现一些异常情况,比如一方的机器突然断电,这时要过很久后才能得知该TCP链接已经断掉。如何才能很快知道该TCP链接已经断了?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
基于IOCP的服务器,经常会发生客户端断开连接。由于网络经常出现一些异常情况,比如一方的机器突然断电,这时要过很久后才能得知该TCP链接已经断掉。如何才能很快知道该TCP链接已经断了?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(5)
GetQueuedCompletionStatus不能得出网络是否异常了,比如客户端拔网线,比如突然重启,这些是无法捕获的。这是由于TCP协议本身的问题,其实细想一下,客户端还没有把数据发送缓冲区时系统就崩溃了,这种情况下肯定无法捕获的,只能通过应用协议来判断了。常用的解决方法三种:
定时心跳包,超时没收到回应,就认为客户端就是断开了。
通过SO_KEEPALIVE来判断,默认是2小时进行一次检测,自己也可以设置检测间隔,但会影响其它系统所有正在使用的Socket,慎用
通过SIO_KEEPALIVE_VALS,该选项不同于SO_KEEPALIVE 机制的就是它是针对单个连接的,对系统其他的Sokcet并不影响。
用户层的心跳包检测机制必不可少,客户端端定时发送用户层心跳包,服务器端针对每个已连接套接字记录最后一次收到心跳包的时间,同时开启线程定时检测:超过XX秒还未收到心跳包的套接字,kill掉,释放占用的上下文及收发缓冲区资源。
一般都是定时发送消息吧,即心跳包,不知道还有其他什么方法不。关注。
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! %dn",hSocket);
continue;
}
else if (dwBytesTransferred ==0)
{
proxy->SafeClose(lpOvlpEx);
TRACE(".....................%d..........closed & freed........n",hSocket);
continue;
}
}
上面的GetQueuedCompletionStatus是接收IOCP通知的主要函数,通过dwBytesTransferred、hCompletionSocket、lpOvlpEx以及返回值r即可判断出客户端是否关闭。
一般都是客户端发送心跳ping包,如果 ping 包没有回应,则客户端认为掉线了,对于服务器来说,如果完成端口没有反应了,则会调用 GetQueuedCompletionStatus 函数来判断