Hands-On Network Programming with C

Written By Lewis Van Winkle

Bind fails with error 98 (or error 10048)

A common socket programming error I hear about is error 98 (EADDRINUSE) or 10048 (WSAEADDRINUSE) from bind().

The Setup

Maybe you are programming a server in C or C++. Your socket code might use a setup like this:

//Cross-platform error code
#if defined(_WIN32)
#define GETSOCKETERRNO() (WSAGetLastError())
#else
#define GETSOCKETERRNO() (errno)
#endif

//Set port to bind to.
struct addrinfo *address;
getaddrinfo(0, "8080", &hints, &address);

//Create socket.
SOCKET socket_listen;
socket_listen = socket(address->ai_family,
    address->ai_socktype, address->ai_protocol);

//Bind socket to local port.
if (bind(socket_listen, address->ai_addr, address->ai_addrlen)) {
    fprintf(stderr, "bind() failed. Error: %d\n", GETSOCKETERRNO());
    return 1;
}

If your call to bind fails, the first thing to do is check the error code. The error is stored in errno on Linux, but on Windows you will need to call WSAGetLastError().

If the error returned by bind() is 98 (Linux) or 10048 (Windows), then it means the local port you are trying to bind to is already in use.

Getting the Error Message

By the way, you can also get the error message in text form.

On Linux it is just a call to strerror(). For error 98, that will return something such as "Address already in use".

Getting the error text on Windows is a bit trickier. There are instructions on getting the Windows error text here. The error message on Windows may be similar to "Only one usage of each socket address (protocol/address/port) is normally permitted."

In any case, now that you know the what the error is, how do you fix it?

What causes "Address already in use error"

Basically, only one program can listen on a given protocol/address/port tuple at any given time. If more than one program were permitted to listen, then the operating system wouldn't know which program to send incoming connections to.

When I hear about this error from readers, there is usually one of three causes.

1. Another program is using that port

The most obvious cause for the error is that another program is using the port you want to listen on. In this case, you can change the port your program listens on, or you can close the other program that is using that port.

On Linux, you can see which other programs are listening for connections using the netstat -ntlp command. The ntlp stands for "numeric tcp listen programs". In order words, we are asking netstat to show port numbers (numeric), to only show TCP sockets, to only show sockets in the listening state, and to show which programs are using the sockets.

The following screenshot shows using the netstat command on Linux to find which program is tying up port 8080.

screenshot showing usage of netstat command to find which program is using a given port

As you can see above, the program tying up port 8080 is "server1" with a PID of 96939. Knowing the PID, you can easily kill the program if you like. Just please be sure you know what the program is and whether you really need it or not before you go around terminating things willy-nilly.

Windows also has a netstat command, but the usage is different. On Windows you can show all listening sockets with the command netstat -nao -p TCP | findstr LISTEN. Window's netstat command doesn't have an easy way to filter only listening sockets, so the findstr program comes in handy. In any case, running that command will list each listening TCP socket and show the owner program's PID for each socket.

The following screenshot shows the usage of netstat on Windows to see which program is using port 8080:

screenshot showing usage of netstat on Windows to find which program is using port 8080

As shown in the above screenshot, netstat lists each program's listening address and PID. You can get more info on a PID with the tasklist command. For example, running tasklist | findstr 50396 would get us the program name for PID 50396 — the process we identified as using port 8080. For example:

screenshot showing tasklist to get program name from a PID

The above screenshot shows that the program "server1.exe" has the PID of 50396, and therefore is the program using port 8080.

2. Your program is already running

This is more common than you think. Is your program already running? If it is, then of course the port is already in use!

This also isn't always as easy to determine as you might like. In the server world, it's very common for programs to run in the background or as daemons. In any case, if you get a bind() error or address already in use error, be sure to check that your program isn't already running.

3. TCP Linger / TIME-WAIT

I've saved the most complicated scenario for last. Suppose your server program is running, and then you terminate it (or it crashes). When you restart it, you get the address in use error (EADDRINUSE or WSAEADDRINUSE). However, if you wait a couple minutes, you are able to start your program without error. What is going on here?

I won't go into too much depth here (read my book for that), but basically when a socket is closed it can go into a TIME-WAIT state on the end that initiated the close. This isn't a problem for a client program, since it doesn't use bind() anyway (typically). However, this TIME-WAIT state can be a problem for server applications. It means the operating system is still keeping track of the closed socket, even after your entire program is closed. This is enough to cause the "Address already in use" error if you restart your program.

Now, there is an easy way to prevent this error. You can use the SO_REUSEADDR socket option before calling bind(). It looks like this:

int yes = 1;
if (setsockopt(socket, SOL_SOCKET, SO_REUSEADDR,
                        (void*)&yes, sizeof(yes)) < 0) {
    fprintf(stderr, "setsockopt() failed. Error: %d\n", GETSOCKETERRNO());
}

This option will allow bind() to succeed even if a few TIME-WAIT connections are still around. There is very little downside to using the SO_REUSEADDR, so I suggest most server applications use it.

In any case, check out Chapter 13 of my book for more information.

Summary

If bind() causes error 98 (EADDRINUSE) or 10048 (WSAEADDRINUSE), it means you are trying to bind to a local port that is already in use. This is usually caused by one of three reasons:

  1. Another program is already using that port.
  2. Your program is already running and you've attempted to start it a second time.
  3. Your program was running recently and some connections are still lingering around in the half-dead TIME-WAIT state.

Cause 1 can be fixed by terminating the program using your port, or having your program use a different port.

Cause 2 can be fixed by only running one instance of your program at a time.

Cause 3 can be fixed by waiting a few minutes or using the SO_REUSEADDR socket option.




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