我已经在使用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。如果您不需要那种优化(不需要),那就不要这样做。