Thread: WSAGetLastError() is returning 0

  1. #1
    Registered User
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    217

    WSAGetLastError() is returning 0

    Hello. I'm making a server emulator for a game someone else made. In the code i check the return value of "recv" to see if the player has disconnected. When recv() returns -1 it could mean they disconnected OR it could just mean there is no data to receive on a non blocking socket. For some reason WSAGetLastError() returns 0 even after recv returns a -1. Heres the code:

    Code:
    int Player::RecvPackets()
    {
        int size = 1;
        while(size > 0)
        {
            char buffer[0xFFFF];
            size = socketId->Read(buffer, 2);
    
            if(size == 2)
            {
                unsigned short dataLen = ((unsigned short)buffer[0] << 8) + (unsigned short)buffer[1];
    
                //Receive all the data
                unsigned short received = 0;
                while((size = socketId->Read(&buffer[received], dataLen - received)) > 0 && received < dataLen)
                    received += size;
    
                if(received == dataLen)
                {
                    char uncompressedData[0xFFFF];
                    size_t cLen = sizeof(uncompressedData) - 1;
    
                    //decompress the received data
                    if(uncompress((Bytef*)uncompressedData,(uLongf*)&cLen,(const Bytef*)buffer, dataLen) == Z_OK)
                    {
                        uncompressedData[cLen] = 0;
    
                        vector<string> packetList = TokenizeString(uncompressedData, "\n");
                        for(unsigned int i = 0; i < packetList.size(); ++i)
                        {
                            ByteStream packet(packetList[i]);
    
                            if(firstPacket)
                                ParseLoginPacket(packet);
                            else ParsePacket(packet);
                        }
                    } else {
                        server << LogHeader() << "Decompression error\n";
                        Disconnect("Decompression error");
                        break;
                    }
                } else {
                    server << LogHeader() << "Bytes received doesn't match the packet size\n";
                    Disconnect("Invalid packet length");
                    break;
                }
            } else if(size > 0) {
                server << LogHeader() << "Couldn't receive packet size\n";
                Disconnect("Network error");
                break;
            }
    
            if(size == 0 || (size < 0 && soxLastError() != EWOULDBLOCK))
            {
                server << LogHeader() << "Player left with socket error " << soxLastError() << "\n";
                Disconnect();
            }
        }
        return 1;
    }
    The last few lines is where the player keeps getting disconnected. First it checks if size returned 0 which means disconnection. Then it checks if size returns a negative which means error. If it did return negative than it checks if the error isn't due to non blocking. If it's not because of non blocking than it needs to remove the player. The player always gets disconnected (it only prints out one "Packet received" before disconnecting) and soxLastError() (which is just WSAGetLastError()) always returns 0 instead of EWOULDBLOCK or some other error.

    NOTE: Socket::Read() just calls recv().
    Last edited by 39ster; 07-16-2008 at 06:22 AM.

  2. #2
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    you are calling soxLastError() twice - so obviously - second call will return 0 - store the result of the first call and print it
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  3. #3
    Registered User
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    217
    I didn't think WSAGetLastError() changes the error. I just tried storing it and i get the same result...0.

    EDIT: If i remove the condition, the socket still works and i can still receive packets.

    EDIT: Now i just removed the "Disconnect()" so it only prints when it gets an error. It only prints once (rather than over and over again each time ::RecvPackets is called)

    EDIT: Ok it prints every now and then. e.g

    Code:
    [07/16/08 23:18:27][SERVER] Listening on port 14804
    [07/16/08 23:18:29][PLAYER:guest] New player has connected.
    [07/16/08 23:18:29][PLAYER:guest] Sent..
    [07/16/08 23:18:29][PLAYER:guest] Received: 37
    [07/16/08 23:18:29][PLAYER:guest] Received: 39
    [07/16/08 23:18:29][PLAYER:guest] Player left with socket error 0
    [07/16/08 23:18:29][PLAYER:guest] Sent..
    [07/16/08 23:18:29][PLAYER:guest] Received: 34
    [07/16/08 23:18:29][PLAYER:guest] File Request: head1.png
    [07/16/08 23:18:29][PLAYER:guest] Received: 34
    [07/16/08 23:18:29][PLAYER:guest] File Request: body1.png
    [07/16/08 23:18:29][PLAYER:guest] Received: 2
    [07/16/08 23:18:29][PLAYER:guest] Received: 34
    [07/16/08 23:18:29][PLAYER:guest] File Request: steps.wav
    [07/16/08 23:18:29][PLAYER:guest] Received: 34
    [07/16/08 23:18:29][PLAYER:guest] File Request: walk.gani
    [07/16/08 23:18:29][PLAYER:guest] Received: 2
    [07/16/08 23:18:30][PLAYER:guest] Received: 2
    [07/16/08 23:18:30][PLAYER:guest] Received: 2
    [07/16/08 23:18:30][PLAYER:guest] Received: 2
    [07/16/08 23:18:30][PLAYER:guest] Received: 2
    ....
    ....
    ....
    [07/16/08 23:19:25][PLAYER:guest] Player left with socket error 0
    [07/16/08 23:19:25][PLAYER:guest] Received: 2
    [07/16/08 23:19:25][PLAYER:guest] Received: 2
    [07/16/08 23:19:25][PLAYER:guest] Received: 2
    [07/16/08 23:19:25][PLAYER:guest] Received: 2
    [07/16/08 23:19:25][PLAYER:guest] Received: 2
    [07/16/08 23:19:27][PLAYER:guest] Received: 2
    EDIT: Now i changed the receive code to this:
    Code:
                //Receive all the data
                unsigned short received = 0;
                size = socketId->Read(buffer, dataLen);
                //while((size = socketId->Read(&buffer[received], dataLen - received)) > 0 && received < dataLen)
               //     received += size;
    and it works but i get errors about the amount of bytes received not matching dataLen every now and then


    EDIT!!!!:: Ok i fixed it

    Code:
                //Receive all the data
                unsigned short received = 0;
    
                while(received < dataLen)
                {
                    if((size = socketId->Read(&buffer[received], dataLen - received)) > 0)
                        received += size;
                    else break;
                }
    It called recv one too many times (as it called recv before it checked if received < dataLen)
    Last edited by 39ster; 07-16-2008 at 07:38 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Stop GUI Application returning when run
    By DaveHope in forum Windows Programming
    Replies: 7
    Last Post: 06-29-2009, 08:57 PM
  2. function returning hour in either 12 or 24 hour format
    By stanlvw in forum C Programming
    Replies: 4
    Last Post: 01-01-2008, 06:02 AM
  3. Recursion: base case returning 1, function returning 0
    By yougene in forum C Programming
    Replies: 5
    Last Post: 09-07-2007, 05:38 PM
  4. Function returning incorrect value
    By CHurst in forum C Programming
    Replies: 3
    Last Post: 12-13-2005, 01:27 PM
  5. Please Help - Problem with Compilers
    By toonlover in forum C++ Programming
    Replies: 5
    Last Post: 07-23-2005, 10:03 AM