Reputation: 1
I have a non-blocking socket server which supports all connecting clients. It's using multi-threading and it's cross-compilable using GCC.
It works perfect (as I want) in Linux, but when I try to use it in Windows, when I send a 70MB of file through it, it loses around 20MB from the file.
All sockets are non-blocking, so for recv/send socket calls, I don't have check/stop. It's in a loop and it sends what it receive, it sort of acts as a Echo server, but it loses data in Windows. I'm using Winsock 2.2 in WSAStartup.
What is wrong? How can I have wait/flush send calls, but never block recv calls? (if this is the issue)
Code pieces: How I make it non-blocking:
iMode = 1;
ioctlsocket(sock1,FIONBIO, &iMode);
ioctlsocket(sock2,FIONBIO, &iMode);
How I send/receive between two sockets:
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);
}
}
Upvotes: 0
Views: 1185
Reputation: 598001
int count = recv(sock1, buffer, sizeof(buffer), 0); receiveResult = WSAGetLastError(); if (receiveResult == WSAEWOULDBLOCK && count <= 0)
When calling recv()
or send()
, WSAGetLastError()
will return a meaningful value only if -1 (SOCKET_ERROR
) is returned, but you are also checking it when 0 is returned instead. They do not set an error code for WSAGetLastError()
when returning >= 0. You need to separate those conditions.
Also, just because you have read X number of bytes does not guarantee that you will be able to send X number of bytes at one time, so you need to check send()
for WSAEWOULDBLOCK
until you have no more data to send.
Try something more like this:
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;
Upvotes: 1