Search code examples
c++udprecvfrom

Getting undocumented error code from recvfrom


When attempting to read UDP packets using recvfrom the function returns -1 indicating an error. I of course then call WSAGetLastError to find out what the problem is. The reported error number is 183. I cant seem to find any reference as to what that number means.

Edit:

while (bytesRecv != SOCKET_ERROR)
    {
        //  get data from the server
        bytesRecv = recvfrom(m_socket, (char*)&receiveData, sizeof(ReceiveData), 0, (struct sockaddr *) &server_addr, &server_addr_len);
        logError("Bytes recieved: ", bytesRecv);
        // if data was recieved from the server
        if (bytesRecv > 0)
        {
            //Data packet processing code
        }
        else
        {
            if (bytesRecv == SOCKET_ERROR)
            {
                logError("Error: Reading data: ", WSAGetLastError());
            }
        }
    }

Edit:

void logError(const std::string &text, int errorCode)
{
    std::ofstream log_file("error_log_file.txt", std::ios_base::out | std::ios_base::app);

    log_file << text << errorCode << "\n";
}

Solution

  • The problem is not with WSAGetLastError() itself. The real problem is that you are calling logError() before calling WSAGetLastError(), and logError() ends up resetting the last error code to 183.

    logError() uses a std::ofstream to open a file for appending. On Windows, that operation will ultimately call CreateFile() with the OPEN_ALWAYS flag, for which its documentation states:

    Opens a file, always.

    If the specified file exists, the function succeeds and the last-error code is set to ERROR_ALREADY_EXISTS (183).

    If the specified file does not exist and is a valid path to a writable location, the function creates a file and the last-error code is set to zero.

    ...

    If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.

    Internally, WSAGetLastError() simply maps to GetLastError() (a well-known but undocumented implementation detail). So, no matter whether the CreateFile() succeeds or fails in opening the file, the error code reported by WSAGetLastError() will get reset to the result of the open operation.

    Your call to logError() is in the wrong place. It needs to be moved inside of your if (bytesRecv > 0) block (BTW, UDP supports 0-length datagrams, so you should be using >= instead of >):

    while (true)
    {
        //  get data from the server
        bytesRecv = recvfrom(m_socket, (char*)&receiveData, sizeof(ReceiveData), 0, (struct sockaddr *) &server_addr, &server_addr_len);
        // if data was received from the server
        if (bytesRecv >= 0)
        {
            logError("Bytes received: ", bytesRecv); // <-- moved here!!!
            //Data packet processing code
        }
        else // if (bytesRecv == SOCKET_ERROR)
        {
            logError("Error: Reading data: ", WSAGetLastError());
            break;
        }
    }
    

    Alternatively:

    while (true)
    {
        //  get data from the server
        bytesRecv = recvfrom(m_socket, (char*)&receiveData, sizeof(ReceiveData), 0, (struct sockaddr *) &server_addr, &server_addr_len);
        // if data was received from the server
        if (bytesRecv == SOCKET_ERROR)
        {
            logError("Error: Reading data: ", WSAGetLastError());
            break;
        }
    
        logError("Bytes received: ", bytesRecv); // <-- moved here!!!
        //Data packet processing code
    }