If i start local server on Linux, i get "Address already in use" error.
I use setsockopt(SO_REUSEADDR) but it doesn’t help. How can i solve this problem?
Code:
#include <iostream>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
using namespace std;
int main() {
sockaddr_un s_addr;
s_addr.sun_family = AF_UNIX;
strcpy(s_addr.sun_path, "server");
int s_descriptor = socket(AF_UNIX, SOCK_STREAM, 0);
const int par = 1;
if (setsockopt(s_descriptor, SOL_SOCKET, SO_REUSEADDR, &par, sizeof(int)) < 0){
cout << "Error setsockopt()";
return -1;
}
if (bind(s_descriptor, (sockaddr *)&s_addr, sizeof(s_addr)) < 0) {
cout << "Error with bind()\n";
cout << strerror(errno);
return -2;
}
close(s_descriptor);
return 0;
}
>Solution :
You are attempting to create an AF_UNIX socket. AF_UNIX sockets create a filesystem pipe node to handle connections.
In this case EADDRINUSE means that the filesystem node already exists. Nothing might actually be listening on it, but it exists, and bind() fails for that reason. It’s a quirk of how AF_UNIX sockets work. SO_REUSEADDR is for AF_INET or AF_INET6 sockets, and does not do much for AF_UNIX sockets.
strcpy(s_addr.sun_path, "server");
You will be surprised to find a server special pipe file in your current directory. That’s the culprit. The solution is very simple:
unlink("server");
Just before you bind(), and now you can bind it.
If you’ve been paying attention you will now be wondering if anything stops multiple instances of your server starting, creating and bind()ing to this AF_UNIX socket, and rudely unlinking its predecessor’s listening socket, leaving you with multiple instances of the server process, all but one of them now completely useless. This is correct, nothing will stop you from doing that.
Which is why AF_UNIX servers will typically employ other means to ensure that only one instance of them is running, like a separate lock file. But that’s going to be a separate question…