各位,不知道大家有遇到过IOCP中WSASend投递成功但GetQueuedCompletionStatus不返回的情况没,我是通过一个client端不断的测试该iocp服务器程序后得到的结论;我这个client端测试程序会不停的连服务器程序,然后随机断开某些socket,然后再重新连如此反复,连上的socket会给iocp服务器程序发送一些数据包,接收服务器原样发回的数据包,总之就是个测试iocp服务器程序是否能够支持相对多有一点连接(1000-2000连接)、是否够健壮的一个client端程序,服务器也会在一定的时间(20秒)内对依然连接进来的socket进行强制踢出closesocket操作;按照消息约定格式,我收到一个消息后入消息队列,通知线程池中线程去处理,处理后把消息扔到发送消息队列(这里我是原样把收到的消息发送到发送消息队列),然后系统中有专门的一个线程负责将发送消息队列中的消息用WSASend发送出去,我分别对recv和send做计数,保证同一时刻只有一个recv和一个send,完成并返回后再投递新的WSARecv或者WSASend();对于GetQueuedCompletionStatus()返回的失败信息,凡是和SEND有关的信息,我都打印出来以供识别(发现并没有这些SEND信息出现,也就是说,除WSASend()发送完成的通知通过GetQueuedCompletionStatus()正常返回外,没有发现返回的和投递WSASend有关的异常或者错误信息;当收到GetQueuedCompletionStatus()返回的失败或者成功且字节为0的信息(说明对方或者自己方closesocket),我把该socket相关的上下文结构扔到一个队列去,该队列不释放资源只用于观察,发觉该队列中确实有挂起的WSASend()没有返回,并且等待了10几分钟依然没有返回,所以,我得到的结论是IOCP中WSASend投递成功但可能在某些极端的情况下(比如client突然断开,或者我突然在某个单独的线程中把该client踢出去(closesocket)等比较复杂的网络情况下,导致WSASend投递成功但GetQueuedCompletionStatus不返回针对该WSASend投递的结果信息;在我程序的书写中,虽然频繁的连接,断开,频繁的收发数据包,但这种WSASend投递成功但GetQueuedCompletionStatus不返回的情况依然非常罕见(大概1小时才出现一次)。这里想请教各位,是否有朋友也进行过这方面的测试,确认WSASend投递成功在某种极端的情况下确实会导致GetQueuedCompletionStatus不返回和该WSASend投递有关的回馈信息,也欢迎大家讨论该问题;

解决方案 »

  1.   

    你上面说WSASend()没有返回,后面又说GetQueuedCompletionStatus没有返回?你返回的标准是什么?是没有捕捉到控制码还是函数挂起了?
      

  2.   

    我更正一下,“WSASend()没有返回”这个描述的不恰当,WSASend()是异步的,肯定是会立即返回的,但
    WSASend()投递成功后,我判断的返回标准是GetQueuedCompletionStatus()函数的返回,也就是说,WSASend()投递若成功,或者返回的失败信息是ERROR_IO_PENDING,我都认为它投递成功。
    既然它投递成功,那么GetQueuedCompletionStatus()函数必然会针对这个成功的投递有一个返回;
    我在文中描述的,正是发现了针对成功的WSASend()投递,
    GetQueuedCompletionStatus()却没有返回。
      

  3.   

    我把所有的GetQueuedCompletionStatus()返回的情况都做了跟踪,得出的结论是,GetQueuedCompletionStatus()没有针对成功的WSASend()投递产生过返回值,可以理解成函数GetQueuedCompletionStatus()挂起.
      

  4.   

    可能的原因:
    1.你的SOCKET没有和完成端口绑定
    2.WCASEND,执行失败了
      

  5.   

    这种情况应该不存在  我一开始也以为是这样的(即投递成功了 没有得到返回或者哪怕是出错的返回)  其他不会出现  多打些log看看就知道了。
    看msdn上一句话
    要记住,如果重叠操作调用失败时(也就是说,返回值是SOCKET_ERROR,并且错误原因不是WSA_IO_PENDING),那么完成端口将不会收到任何完成通知。如果重叠操作调用成功,或者发生原因是WSA_IO_PENDING的错误时,完成端口将总是能够收到完成通知。