Is there any purpose to `bind()` unix domain socket client processes?
The call to bind()
is only required if you need to receive a connection with SOCK_STREAM
type socket, but bind()
behavior depends on the domain of the SOCKET. There is a manual page dedicated to this.
Useful information:
Address format
A UNIX domain socket address is represented in the following structure:
#define UNIX_PATH_MAX 108struct sockaddr_un { sa_family_t sun_family; /* AF_UNIX */ char sun_path[UNIX_PATH_MAX]; /* pathname */};
Three types of address are distinguished in this structure:
pathname: a UNIX domain socket can be bound to a null-terminated file system pathname using bind(2). When the address of the socket is returned by getsockname(2), getpeername(2), and accept(2), its length is offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1, and sun_path contains the null-terminated pathname.
unnamed: A stream socket that has not been bound to a pathname using bind(2) has no name. Likewise, the two sockets created by socketpair(2) are unnamed. When the address of an unnamed socket is returned by getsockname(2), getpeername(2), and accept(2), its length is sizeof(sa_family_t), and sun_path should not be inspected.
abstract: an abstract socket address is distinguished by the fact that sun_path[0] is a null byte ('\0'). The socket's address in this namespace is given by the additional bytes in sun_path that are covered by the specified length of the address structure. (Null bytes in the name have no special significance.) The name has no connection with file system pathnames. When the address of an abstract socket is returned by getsockname(2), getpeername(2), and accept(2), the returned addrlen is greater than sizeof(sa_family_t) (i.e., greater than 2), and the name of the socket is contained in the first (addrlen
- sizeof(sa_family_t)) bytes of sun_path. The abstract socket namespace is a nonportable Linux extension.
Binding to a socket with a filename creates a socket in the file system that must be deleted by the caller when it is no longer needed (using unlink(2)). The usual UNIX close-behind semantics apply; the socket can be unlinked at any time and will be finally removed from the file system when the last reference to it is closed.
So:
bind()
is not necessary in a client.bind()
in your context give a name to yours sockets"a"
and"b"
bind(s0, &sa0, sizeof(sa0) + sizeof("b"));
and similar line in yours code are undefined behavior; it gives a wrong size tobind()
that exceeds the bound of&sa0
. The correct code isbind(s0, &sa0, sizeof sa0);
bind()
in this context (Linux, AF_UNIX) does create a special socket file; if you want to remove it, you must callunlink()
orremove()
.
man bind
gives this answer:
When a socket is created with socket(2), it exists in a name space (address family) but has no address assigned to it. bind() assigns the address specified by addr to the socket referred to by the file descriptor sockfd. addrlen specifies the size, in bytes, of the address structure pointed to by addr. Traditionally, this operation is called “assigning a name to a socket”. It is normally necessary to assign a local address using bind() before a SOCK_STREAM socket may receive connections (see accept(2)).
Calling bind()
on a Unix-domain socket, with no intention of ever calling accept()
, is a very useful way of assuring only one copy of a process is running. It's a lot more robust than relying on a process name, as binaries can be copied and run under another name.
Cleanup on abnormal termination (SIGSEGV
, being the target of kill -9 ...
) is a problem, though. as the socket won't be removed unless your application does it in a signal handler.