简体   繁体   中英

Non-blocking socket loses data on Windows

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);
    }

}
 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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM