我有一个非阻塞套接字服务器,它支持所有连接客户端。它使用多线程,并且可以使用GCC进行交叉编译。
它在Linux中运行完美(我想要的),但是当我尝试在Windows中使用它时,当我通过它发送70MB的文件时,它会从文件中丢失大约20MB。
所有套接字都是非阻塞的,所以对于recv / send套接字调用,我没有检查/停止。它在循环中并且它发送它接收的内容,它有点像Echo服务器,但它在Windows中丢失了数据。我在WSAStartup中使用Winsock 2.2。
有什么问题?我怎样才能有等待/刷新发送呼叫,但从不阻止recv呼叫? (如果这是问题)
代码: 我如何使其无阻塞:
iMode = 1;
ioctlsocket(sock1,FIONBIO, &iMode);
ioctlsocket(sock2,FIONBIO, &iMode);
我如何在两个插座之间发送/接收:
for (;;)
{
memset(buffer, 0, 8192);
int count = recv(sock1, buffer, sizeof(buffer), 0);
receiveResult = WSAGetLastError();
if (receiveResult == WSAEWOULDBLOCK && count <= 0)
continue;
if (count <= 0)
{
closesocket(sock1);
closesocket(sock2);
return;
}
if (count > 0)
{
int retval = send(sock2, buffer, count, 0);
}
}
答案 0 :(得分:1)
int count = recv(sock1, buffer, sizeof(buffer), 0); receiveResult = WSAGetLastError(); if (receiveResult == WSAEWOULDBLOCK && count <= 0)
调用recv()
或send()
时,WSAGetLastError()
仅在返回-1(SOCKET_ERROR
)时才会返回有意义的值,但是当0为0时,您也会检查它而是返回。返回&gt; = 0时,它们不会为WSAGetLastError()
设置错误代码。您需要将这些条件分开。
另外,仅因为您已读取X个字节数并不能保证您一次能够发送X个字节数,因此您需要检查send()
WSAEWOULDBLOCK
,直到您没有更多数据要发送。
尝试更像这样的事情:
bool keepLooping = true;
do
{
int count = recv(sock1, buffer, sizeof(buffer), 0);
if (count > 0)
{
// data received...
char *p = buffer;
do
{
int retval = send(sock2, p, count, 0);
if (retval > 0)
{
p += retval;
count -= retval;
}
else if (retval == 0)
{
// peer disconnected...
keepLooping = false;
}
else if (WSAGetLastError() != WSAEWOULDBLOCK)
{
// a real error occurred...
keepLooping = false;
}
else
{
// peer is not ready to receive...
// optionally use select() to wait here until it is...
}
}
while ((count > 0) && (keepLooping));
}
else if (count == 0)
{
// peer disconnected...
keepLooping = false;
}
else if (WSAGetLastError() != WSAEWOULDBLOCK)
{
// a real error occurred...
keepLooping = false;
}
else
{
// no data is available for reading...
// optionally use select() to wait here until it is...
}
}
while (keepLooping);
closesocket(sock1);
closesocket(sock2);
return;