我已经在使用Winsock的C++ CLI中为服务器编写了套接字。套接字使用异步方法发送,接收和接受连接。在生产环境中实现我的套接字后,发送功能停止工作,并给我错误WSAEWOULDBLOCK。从我对网络的研究中可以看出,这意味着套接字IO的网络缓冲区已满,或者网络太忙而无法执行我的操作。但是,我还没有看到可以解决此问题的任何特定解决方案。我的临时解决方案是围绕WSASend函数创建一个do-while循环,使线程休眠X量的MS,然后重试。这导致比以前的套接字(.NET套接字类)高得多的延迟,并且延迟尖峰较大。

我发送数据的代码如下:

void Connectivity::ConnectionInformation::SendData(unsigned char data[], const int length)
{
    if (isClosed || sendError)
        return;

    Monitor::Enter(this->syncRoot);

    try
    {
        sendInfo->buf = (char*)data;
        sendInfo->len = length;

        do
        {
            state = 0;
            if (WSASend(connection, sendInfo, 1, bytesSent, 0, NULL, NULL) == SOCKET_ERROR)
            {
                state = WSAGetLastError();
                if (state == WSAEWOULDBLOCK)
                {
                    Thread::Sleep(SleepTime);
                    //Means the networking is busy and we need to wait a bit for data to be sent
                    //Might wanna decrease the value since this could potentially lead to lagg
                }
                else if (state != WSA_IO_PENDING)
                {
                    this->sendError = true;
                    //The send error bool makes sure that the close function doesn't get called
                    //during packet processing which could cause a lot of null reffernce exceptions.
                }
            }
        }
        while (state == WSAEWOULDBLOCK);
    }
    finally
    {
        Monitor::Exit(this->syncRoot);
    }
}

当我能够发送数据时,是否可以使用例如WSAEventSelect方法来获取回调?从MSDN上的文档中,等待数据方法也可能卡在此错误中。任何人都可以解决这个问题吗?

最佳答案

错误代码WSAEWOULDBLOCK表示您试图在非阻塞套接字上进行操作,但是该操作无法立即完成。这不是真正的错误-这意味着您可以稍后重试或安排异步IO(这不会失败)。但这不是您最初想要的。让我解释:

您应该通过以下两种方式之一使用套接字:

  • 同步,阻止。
  • 异步,非阻塞,基于回调。

  • 您正在混合使用这两种方法,这会使两者都变得最糟。您创建了一个非阻塞套接字,并以潜在的阻塞方式使用它。

    las,我还没有完全资格为本地代码套接字提供最佳实践。我建议您阅读所有的docs for WSASend,因为它们似乎可以解释所有这些内容。

    现在,为什么还会出现这个奇怪的错误代码?这是一项性能优化。您可以推测性地尝试同步发送(非常快)。而且只有在失败的情况下,才应该安排异步IO。如果您不需要那种优化(不需要),那就不要这样做。

    10-06 14:58