IOCP中 客户异常断开时, 服务器端GetQueuedCompletionStatus执行了好多遍,且都是返回0,如何解决?

zcyou 2017-01-12 05:35:45
GetQueuedCompletionStatus 函数返回0 且GetLastError 得到的错误码为 122(ERROR_INSUFFICIENT_BUFFER) ,
同一个客户端断开,处理了N多遍是什么原因。在第一次进来的时候我都直接closesocket了。后面怎么还会进来。而且是一瞬间来了很多次。处理结果打印如下图。求救!!!!!
...全文
505 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
亚细亚 2021-06-28
  • 打赏
  • 举报
回复

对于已经连接的一个socket上,当服务器端执行closesocket()关闭这个socketid时,为什么会有好多次GetQueuedCompletionStatus的返回,并且返回值都时0,问题到底出在哪里?

亚细亚 2021-06-28
  • 打赏
  • 举报
回复

我也遇到同样的问题,怎么解决?

gnorth 2018-01-18
  • 打赏
  • 举报
回复
先假设你没有在客户端断开连接的时候对套接字进行WSASend WSARecv等操作,因为这个是低级错误,不应该犯. 我猜想,你一定写了超时检查吧.或者有一个IOCP工作线程之外的线程,对套接字进行操作了. 我先假设这样一种情况, 客户端超时了,例如客户端10秒没收到数据,被你的心跳检查线程检查出来了, 这时候你的心跳检查线程将套接字closesocket掉, 这之前,如果你的套接字投递了任何操作,在closesocket,你的IOCP线程中的GetQueuedCompletionStatus会返回关联这个套接字的重叠结构,并且完成字节数为0, 然后你的IOCP工作线程又去执行一次closesocket,然后,就有问题了. 我们再来看心跳检查线程,closesocket之后,如果你是用了套接字池,你会重新创建一个套接字,然后又把它AcceptEx出去等待连接. 然后你发现问题了吗? 心跳检查线程closesocket, WSASocket, AcceptEx IOCP工作线程得到完成字节0, closesocket,这时,你的心跳线程刚好AcceptEx完,然后你的另外一个IOCP工作线程又返回这个套接字完成字节数为0的,又去closesocket,AcceptEx, 然后就由两个IOCP工作线程无限的死循环,两个线程一直在closesocket, AcceptEx. 解决这个问题的办法,就是你的心跳线程释放,重用资源的同时,对所有工作线程进行互斥,每个工作线程一个临界区,心跳线程来互斥所有这些临界区.或者closesocket统一由一个指定的线程完成,两者各有利弊吧,具体要看你的业务逻辑跟Net IO是如何关联的.
xian_wwq 2017-01-13
  • 打赏
  • 举报
回复
使用WSAGetLastError,看看是什么错误 如果是997,直接回收资源就行
zcyou 2017-01-13
  • 打赏
  • 举报
回复
引用 2 楼 xian_wwq 的回复:
GetQueuedCompletionStatus 函数返回0 说明该连接已经异常了 如果socket被close,则与该socket关联的 所有的未完成投递都会返回 如果投递模型是批量进行, 那么返回的肯定是大批的 出错不要紧,释放投递的对象就可以了
正常情况下我测试就只会进来一次。但在服务器正常运行起来的时候,有时候会在一瞬间出现上图那种大量的打印。我想搞清楚这个到底是什么问题引起的。
zcyou 2017-01-13
  • 打赏
  • 举报
回复
引用 3 楼 VisualEleven 的回复:
你close socket以后,有释放之前分配的内存吗?
没有释放,我把它回收管理起来了
Eleven 2017-01-13
  • 打赏
  • 举报
回复
你close socket以后,有释放之前分配的内存吗?
xian_wwq 2017-01-13
  • 打赏
  • 举报
回复
GetQueuedCompletionStatus 函数返回0 说明该连接已经异常了 如果socket被close,则与该socket关联的 所有的未完成投递都会返回 如果投递模型是批量进行, 那么返回的肯定是大批的 出错不要紧,释放投递的对象就可以了
zcyou 2017-01-13
  • 打赏
  • 举报
回复
引用 6 楼 xian_wwq 的回复:
使用WSAGetLastError,看看是什么错误 如果是997,直接回收资源就行
错误就是122 ERROR_INSUFFICIENT_BUFFER 这个
zcyou 2017-01-12
  • 打赏
  • 举报
回复
相关代码如下:
BOOL bRet = GetQueuedCompletionStatus(pParam->pIOCPModel->m_hIOCP, &dwByteTransfer, (PULONG_PTR)&pSockContextVoid, &pOverLapped, INFINITE);
if (!bRet)
{ //此处代码为什么同一个客户端断开引起进来好多次
DWORD dwError = GetLastError();
if (dwError == 0)
{
continue;
}
if (!pParam->pIOCPModel->HandleError(pSockContext,dwError))
{
break;
}
continue;
}
1、本课程是一个干货课程,主要讲解如何封装服务器底层,使用Tcp/ip长连接,IDE使用vs2019 c++开发以及使用c++11的一些标准,跨平台windows和linux,服务器性能高效,单服务器压力测试上万无压力,服务器框架是经历过上线产品的验证,框架简单明了,不熟悉底层封装的人,半个小就能完全掌握服务器框架上手写业务逻辑。2、本课程是一个底层服务器框架教程,主要是教会学员在windows或linux下如何封装一个高效的,避免踩坑的商业级框架,服务器底层使用初始化即开辟内存的技术,使用内存池,服务器运行期间内存不会溢出,非常稳定,同服务器使用自定义哈希hashContainer,在处理新的连接,新的数据,新的封包,以及解包,发包,粘包的过程,哈希容器性能非常高效,增、删、查、改永远不会随着连接人数的上升而降低性能,增、删、查、改的复杂度永远都是恒定的O(1)。3、服务器底层封装没有使用任何第三方网络库以及任何第三方插件,自由度非常的高,出了任何BUG,你都有办法去修改,查找问题也非常方便,在windows下使用iocp,linux下使用epoll.4、讲解c++纯客户端,主要用于服务器之间通信,也就是说你想搭建多层结构的服务器,服务器与服务器之间使用socket通信。还可以使用c++客户端做压力测试,开辟多线程连接服务器,教程提供了压力测试,学员可以自己做压力测试服务器性能。5、赠送ue4和unity3d通信底层框架以及多人交互demo,登录,注册,玩家离开,同步主要是教会学员服务器与客户端如何交互。6、赠送c++连接mysql数据库框架demo,登录,注册,玩家离开数据持久化.7、服务器教程使用自定义通信协议,同也支持protobuf,选择权在开发者自己手里,想用什么协议都可以,自由度高。8、服务器教程使用手动敲代码逐句讲解的方式开展教学课程。非喜勿喷,谢谢大家。9、服务器教程提供源码,大家可以在平台提供的地址下载或者联系我,服务器使用c++11部分标准,std::thread,条件变量,线程锁,智能指针等,需要学员具备一定c++知识,购买前请慎重考虑。

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧