Hands-On Network Programming with C

Written By Lewis Van Winkle

How to check the return value of socket()

So you call the socket() function to create a new socket, but how do you know if it failed? Well, that depends on your operating system.

socket() on Windows

On Windows (Winsock), socket() returns an unsigned int. When it fails, it will return INVALID_SOCKET which is defined in the Windows header files.

So on Windows, you can check your call to socket() as follows:

unsigned int my_socket = socket(...);
if (my_socket == INVALID_SOCKET) {
    //call to socket() failed
} else {
    //call to socket() succeeded
}

socket() on Linux and macOS

On unix-like platforms (Berkeley sockets), socket() returns an int. This return value will be 0 or positive if the call succeeded, and it will be negative if it failed.

So Linux or macOS, you can check the call to socket() as follows:

int my_socket = socket(...);
if (my_socket < 0) {
    //call to socket() failed
} else {
    //call to socket() succeeded
}

Cross-platform code

It's a bit tedious to have separate error-checking logic for different platforms, so I suggest you use a few macros to make things easier.

The first issue is that a socket is represented as an unsigned int on Windows but as just a plain signed int elsewhere.

Now, it turns out the Windows uses a typedef for SOCKET. So on Windows, you can use the SOCKET type instead of unsigned int. Other systems don't define SOCKET, but if you define SOCKET on those systems, then you can simply use the SOCKET type anywhere.

For example, the following macro can give us a SOCKET type on Linux and macOS:

#if !defined(_WIN32)
#define SOCKET int
#endif

Now, with one consistent type defined, you can use the following code to store a socket:

SOCKET my_socket = socket(...); //cross-platform

This still leaves the problem of checking for a valid socket in a cross-platform manner. Rembering that valid sockets are non-negative on unix-like systems, and that valid sockets are not INVALID_SOCKET on Windows, it's pretty straight forward to define a cross-platform macro to check if a given socket is valid or not.

The following macro will tell if a given socket is valid:

#if defined(_WIN32)
#define ISVALIDSOCKET(s) ((s) != INVALID_SOCKET)
#else
#define ISVALIDSOCKET(s) ((s) >= 0)
#endif

Now, with the SOCKET macro and the ISVALIDSOCKET() macro, you can create a new socket and test if it's valid in a cross-platform manner. It would look like this:

SOCKET my_socket;
my_socket = socket(...);
if (!ISVALIDSOCKET(my_socket)) {
    fprintf(stderr, "socket() failed!\n");
    ...
}

If the call to socket() did fail, then getting the error code is a bit different for each platform. On Windows, a call to WSAGetLastError() is used, while on Linux and macOS the last error is stored in the errno global variable.

While we're here, it might also be a good time to mention that sockets are closed on Windows using closesocket(), which other platforms just use close().

If we take all these platform difference together, you might want the following macros to make cross-platform coding a bit easier.

#if defined(_WIN32)
//Windows already defines SOCKET
#define ISVALIDSOCKET(s) ((s) != INVALID_SOCKET)
#define CLOSESOCKET(s) closesocket(s)
#define GETSOCKETERRNO() (WSAGetLastError())
#else
#define SOCKET int
#define ISVALIDSOCKET(s) ((s) >= 0)
#define CLOSESOCKET(s) close(s)
#define GETSOCKETERRNO() (errno)
#endif

You can then write cross-platform code like the following:

SOCKET my_socket;
my_socket = socket(...);
if (!ISVALIDSOCKET(my_socket)) {
    fprintf(stderr, "socket() failed! Error: %d\n", GETSOCKETERRNO());
}
...
CLOSESOCKET(my_socket);

Now, it might be useful to get a error message instead of only an error code. If that appeals to you, check out this article on how to get socket error messages.

Summary

The return value of socket() depends on whether you are using Windows or a different platform.

On Windows/Winsock, socket() returns an unsigned int. The return value will be INVALID_SOCKET if the call to socket() failed.

On Linux and macOS, socket() returns an int. The return value will be negative if the call to socket() failed.

You may also be interested in how to get error messages or the difference between Windows and other platforms for socket programming.




I hope you found this article helpful. I'd love to hear any feedback you might have. Don't hesitate to get in touch.

You can find the rest of my network programming articles here.

If you found this information helpful, you might be interested in my book.

Purchase on Amazon Purchase on Packt