WSAEWOULDBLOCK handling

WSAEWOULDBLOCK handling

本文关键字:handling WSAEWOULDBLOCK      更新时间:2023-10-16

我已经为使用winsock的C CLI中的服务器编写了套接字。插座正在使用异步方法发送,接收和接受连接。在生产环境中实现了我的插座后,发送功能停止工作,这给了我WSAEWOULDBLOCK的错误。从我在网上的研究中,这意味着插座io的网络缓冲区已满,或者网络忙于此刻,无法进行操作。但是,我还没有看到任何可以解决此问题的特定解决方案。我的临时解决方案是在WSASEND函数周围创建一个循环,使线程为x 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);
    }
}

有没有办法使用方法,例如WSAEEVENTELECT方法,以便在我发送数据时获得回调?从MSDN上的文档中出发,对数据方法的等待也可能陷入此错误。任何人都可以解决这个问题吗?

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

您应该以两种方式之一使用插座:

  1. 同步,阻塞。
  2. 异步,非阻滞,基于回调的。

您正在混合两者,这使您两者兼而有之。您创建了一个非阻滞套接字,并以潜在的阻塞方式使用它。

a,我没有足够的资格为天然代码插座提供最佳实践。我建议您阅读WSASEND的所有文档,因为它们似乎可以解释所有这些。

现在,为什么这个奇怪的错误代码甚至存在?这是性能优化。您可以试图同步发送(非常快)。只有失败,您才应该安排异步IO。如果您不需要该优化(您不需要)不这样做。

正如@USR所说,我需要让lpwsaoverplapped或lpwsaoverlapped_completion_routine设置为一个值,以使操作非阻滞。但是,经过测试后,我发现我需要有一个LPWSAOVERPLAPED对象,以便调用完成程序。在MSDN上也提到了WSASEND函数文档的文档,如果重叠对象和完成例程为null,则插座将以阻塞插座的形式行为。

谢谢,圣诞快乐!:)