IOCP GetQueuedCompletionStatus 返回值处理

来源:互联网 发布:北京人民大学网络教育 编辑:程序博客网 时间:2024/05/08 12:29

有点标题党了,今天不打算将GetQueuedCompletionStatus返回之后的所有事情都来个总结,要讲的只是一个小问题,一个错误:ERROR_NETNAME_DELETED,网络名不再可用。

 

百度一番之后,大多数观点认为:客户端不十分友好的断开以后,服务器工作线程中调用GetQueuedCompletionStatus之后,再调用WSAGetLastError,返回值可能为ERROR_NETNAME_DELETED

 

此观点不是那么正确的。

 

服务器主动这样调用函数shutdown(hSocket,SD_RECEIVE),GetQueuedCompletionStatus之后也会产生ERROR_NETNAME_DELETED,麻烦的是,此时hSocket并没有真正断开,而只是被屏蔽了接收,索性closesocket?一般问题不大,不过本人的设计有些偷工减料,直接closesocket遇到一点小问题。因为客户端异常断开也的确会导致ERROR_NETNAME_DELETED的产生,也就是说,GetQueuedCompletionStatus返回ERROR_NETNAME_DELETED之后,对应的hSocket可能是已经断开的,也有可能还是可用的,而本人事先没有考虑到此种情况,故而不得不重新设计。

这里还有一个问题,shutdown(hSocket,SD_RECEIVE)之后,如果碰巧没轮到GetQueuedCompletionStatus发现问题,而是在WSARecv返回时发生了错误,那么调用WSAGetLastError将会得到一个WSAECONNABORTED或者一个WSAESHUTDOWN错误,这两个错误也是表明:连接通道虽然关了,但套接字资源还未回收。

 

这可如何是好呢?

 

本人索性不shutdown了,直接closesocket,目前还没发现什么大错误。

 

算了,还是说一下GetQueuedCompletionStatus返回值的处理吧,本人也没有遇到过太多情况,处理方法可能也不是太保险,处理过程基本如下(循环就省略了):

if(::GetQueuedCompletionStatus(hPort,&len,(u_long*)&addr_ha_data,(LPOVERLAPPED*)&addr_io_data,INFINITE)==0)

{

      if(addr_io_data==0) return 0;
      if(len==0)
      {
            socket_error(...); continue;
      }

}

if(len==0 || oprate_wsa(...)==0) socket_error(...);

 

oprate_wsa里面当然就是处理收到的或者发送的数据,里面可能会调用WSASend或者WSARecv,调用失败当然就要返回FALSE,也要当成socket_error来处理,socket_error里面当然就是一些清理工作,包括在适当的时候(例如:引用计数为0的时候)释放单句柄数据和closesocket

 

以上……

原创粉丝点击