I am writing C++ socket code using Visual Studio Express 2013 in a .dll project. I am at the point where I am getting an error at this sendto
function:
/* Send data back */
if (sendto(sd, (const char *)sendBuffer,(int)sizeof(sendBuffer), 0,
(struct sockaddr *)&client, sizeof(client)) ==
SOCKET_ERROR)
{
err = WSAGetLastError();
closesocket(sd);
WSACleanup();
throw std::runtime_error("Error sending datagram.");
}
I know that we can get an error code with WSAGetLastError()
, but if I initialize it to a variable I just seem to get junk numbers. How do I extract the sendto
error? I have unit tests written to test this dll, but I'm not sure if there is a way I can just print out the error.
Edit: So after changing the condition to == not != it no longer fails at sendto
but now fails at
bytes_received = recvfrom(sd, readBuffer, NTP_PACKET_MAX, 0, (struct sockaddr *)&client, &len);
if (bytes_received == SOCKET_ERROR)
{
err = WSAGetLastError();
closesocket(sd);
WSACleanup();
throw std::runtime_error("Could not receive datagram.");
}
Like in the original question, i'm unsure of how to get the proper error. When debugging the recvfrom
function, I hover over err
and it says the value it holds is 114351196. From what I can see, that is not a valid Windows Socket Error Code.
Couple of bad mistakes in your code
/* Send data back */
if (sendto(sd, (const char *)sendBuffer,(int)sizeof(sendBuffer), 0,
(struct sockaddr *)&client, sizeof(client)) !=
SOCKET_ERROR) // SHOULD BE == (1)
{
throw std::runtime_error("Error sending datagram.");
// UNREACHABLE CODE (2)
closesocket(sd);
WSACleanup();
}
Error 1: Your error block is entered when you are successfully sending. This may mean that your error is uninitialised (it will be the last error value from somewhere else if not). According to the MSDN documentation for WSAGetLastError
, the function should be called immediately after your WinSocket operation fails, and only in the those circumstances.
If you call it after a successful operation (which you are doing) then there is no guarantee of what value you will receive. If could be the last error from another WinSocket operation on this thread, it may be 0, it may be some other value. The docs do not state what happens if the error is retrieved when no operations have failed, and so you can think of this as undefined behaviour.
Error 2: After you throw your exception the function will exit immediately. You will not call closesocket
or WSACleanup
UPDATE:
I'm guessing that you are checking the value of err
in the debugger before you have assigned it any value. You should be doing something along the lines of:
bytes_received = recvfrom(sd, readBuffer, NTP_PACKET_MAX, 0, (struct sockaddr *)&client, &len);
if (bytes_received == SOCKET_ERROR)
{
int err = WSAGetLastError();
// In debugger you must be here before err is set
closesocket(sd);
WSACleanup();
std::string what{"Could not receive datagram."};
what+= std::to_string(err);
throw std::runtime_error(what.c_str());
}