0

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";
}
cHorse
  • 11
  • 1
  • 8
  • http://forums.codeguru.com/showthread.php?513945-select-accept-fails-183-ERROR_ALREADY_EXSISTS – Nathaniel Johnson Jun 05 '19 at 22:03
  • @NathanielJohnson That forum post doesn't seem to be talking about recvfrom. In any case the error message mentioned doesn't make any sense in context. – cHorse Jun 05 '19 at 22:09
  • 1
    There is no possible way that `WSAGetLastError()` can report 183 (`ERROR_ALREADY_EXISTS`) for a failed `recvfrom()` call. That error code has to be coming from something else, which implies there is a mistake in your error handling code. Since `WSAGetLastError()` just maps to `GetLastError()`, are you making ANY other function call after the failed `recvfrom()` and before the `WSAGetLastError()` that could be resetting the calling thread's error code? Please [edit] your question to show your actual code. – Remy Lebeau Jun 05 '19 at 22:15
  • @RemyLebeau As you can see from the above code there isn't much to be done wrong. I agree that the error code makes no sense which is why I'm here. – cHorse Jun 05 '19 at 22:18
  • As I suspected, you ARE calling something else (specifically, `logError("Bytes recieved: ", bytesRecv);`) before calling `WSAGetLastError()`. So clearly `logError()` is doing something internally that resets the error code before you have a chance to read it in your `if (bytesRecv == SOCKET_ERROR)` block. That call to `logError()` needs to be moved inside of the `if (bytesRecv > 0)` block. And FYI, UDP supports 0-length datagrams, so you should be using `>= 0` instead of `> 0` – Remy Lebeau Jun 05 '19 at 22:21
  • 2
    Your `logError()` function uses a `std::ofstream` to **append to an existing file**. To do that, `ofstream` will ultimately have to call `CreateFile()` with the `OPEN_ALWAYS` flag, for which the [documentation](https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilea) 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.*" – Remy Lebeau Jun 05 '19 at 22:28
  • @RemyLebeau I've posted the `logError()` function. It's just appending the string and integer to a file. The reason it's being called there is an attempt to verify that the number of bytes received is the number of bytes expected. Admittedly the function should be called something else. Thanks for the info on the datagram length. – cHorse Jun 05 '19 at 22:32
  • @RemyLebeau how do I give you credit for solving the mystery? – cHorse Jun 05 '19 at 22:33
  • I posted an answer for you. – Remy Lebeau Jun 05 '19 at 22:37

1 Answers1

2

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
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770