发起WSARecv,WSASend,AcceptEx的线程在请求未完成前退出(也就是GetQueuedCompletionStatus还没返回的情况下退出),则请求取消,错误码995。
错误995很常见,请求未完成时,socket被关闭也是这个错误号,但由于请求发起线程退出而导致的995错误却很少见。一般server端都是在accept或acceptex返回之后投递第一个WSARecv,而acceptex所在线程都是长期存在,GetQueuedCompletionStatus有机会因为线程退出而返回的可能性极小。
client端就不一样了,比如游戏网关,既要干server端的工作,同时又是地图服务器、账号服务器的client,而且还不能断线,一旦发现与地图服务器断开,马上就要重新连接,连接失败再重连,直到连接成功,然后投递WSARecv请求。这种事有时需要在单独线程里去做,不注意就会发生995错误。
解决办法也简单,确保线程退出前,GetQueuedCompletionStatus函数返回一次,等它再次投递WSARecv请求的时候,调用线程就改变了,换成了工作线程,以后只要工作线程不退出,就不会出这种问题。
这里还有另一种办法,就是把第一次WSARecv请求交给工作线程去做,具体可以利用PostQueuedCompletionStatus函数,connect成功以后调用Post函数把CompleteKey,Overlapped直接交给工作线程,让工作线程去调用第一个WSARecv就好了嘛
关键是,完成端口主要还是为server端做的工作比较多,有没有必要为了这个问题特意在工作线程里再加一个判断,倒是个值得衡量的问题。
版权声明:本文为nondeep原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。