winsock select报告一个10022错误(由于一个不明显的原因,需要tcp / winsock guru帮助)

时间:2016-10-31 04:26:41

标签: c++ winsock

给出(简化的代码片段):

const timeval timeout = {100, 0};
for(;;)
{
    fd_set sockets = {2, {service, controlSocket}};
    const auto result = select(0, &sockets, nullptr, nullptr, &timeout);
    ...
    if (result > 0 && FD_ISSET(service, &sockets))
    {
        auto workerConnection = accept(service, nullptr, nullptr);
        WSARecv(workerConnection, ...);
    }
}

其中service是处于侦听状态的套接字,controlSocket是服务套接字上第一个建立的传入连接,用于与管理器通信。

只有在远程端正常关闭任何先前建立的工作连接时,才会发生错误10022。我强调这个代码几乎所有时间都可以工作,除了工作者应用程序关闭连接,但是,我没有声称远程端的关闭连接会影响这种行为。我刚刚注意到这个错误发生在远程端关闭连接之后,而服务端报告了其中一个已建立连接的WAIT_CLOSE。我再次重复一遍,这个代码正常工作,在循环的下一个循环出错后,直到另一个套接字关闭选择工作完全没有错误。错误数等于已建立的workerConnections数。

不知道是否重要我在不使用localhost的同一台PC上测试运行管理器,服务和工作者应用程序的代码而不是我提供PC的网络名称来建立连接。与工作服务应用程序建立连接后,仅通过workerConnection异步接收和发送数据。

问题:由于它根本不影响服务功能,我没有任何其他WSA错误可以忽略此错误并避免发送垃圾邮件日志或我错过了一些重要的事情并且必须解决问题?我怀疑WSA中存在某种问题,因为错误仅在非常特定的情况下发生。我对么?

1 个答案:

答案 0 :(得分:0)

要么我无法正确阅读MSDN文档,要么不清楚,但我的代码中存在重大问题。 MSDN说:

  

注意当发出阻塞Winsock调用(例如select,并将timeout参数设置为NULL)时,Winsock可能需要等待网络事件才能完成调用。在这种情况下,Winsock会执行可警告的等待,这可以通过在同一线程上安排的异步过程调用(APC)来中断。在APC内发出另一个阻塞Winsock调用,该调用在同一个线程上中断正在进行的阻塞Winsock调用将导致未定义的行为,并且永远不会被Winsock客户端尝试。

  

注意无论套接字上的SO_LINGER设置如何,关闭功能都不会阻止。

从我的角度来看,目前还不清楚他们想说什么,但问题是当我用select超时阻塞调用时,即使MSDN声称它没有阻塞,Windows也可以同时执行我提供的回调的WSARecv。在该回调中,我做了另一个同步Winsock调用 - 关闭,即使MSDN声称它没有阻塞。所以我的原始代码完全符合MSDN中提到的导致未定义行为的情况。当我测试调试配置并且只有一个问题时,我的原始问题已经提出。在我开始测试发布配置后,我发现了更多问题。

即使我无法提供对MSDN的引用,我总结如下(这比上面提供的MSDN注释要清楚得多):

除了那些具有LPOVERLAPPED输入参数并且此参数不能为NULL的Winsock函数外,不允许在重叠操作完成后调用窗口调用任何Winsock函数。另一方面,如果他们不使用Winsock,你可以调用其他阻止窗口函数。