1. bind creates a file
As we saw in the previous section, bind() actually creates a file in the filesystem.
- Permissions: The file’s access permissions are determined by your process’s
umaskat the time of creation. - Persistence: The file stays there even after the program exits. You often have to
unlink()(delete) it before running the program again, orbind()will fail withEADDRINUSE.
2. connect checks permissions
When a client tries to connect to a Unix domain socket, the kernel performs filesystem permission checks.
- Requirement: The process must have write permission on the socket file itself and execute permission on every directory in the path leading to that file.
- No auto-binding: Unlike UDP/TCP where the system automatically assigns an ephemeral port if you don’t bind one, calling
connect()on an unbound Unix domain socket does not bind a pathname to it. The client remains “unnamed” (anonymous) unless the programmer explicitly callsbind()beforeconnect().
3. The “Queue Full” Difference (Crucial)
This is a favorite topic in network programming exams.
- TCP behavior: If a server’s listen queue is full and a new TCP SYN arrives, the server usually ignores the packet. It assumes the client will retransmit the SYN later, hoping the queue will have space by then.
- Unix Domain behavior: If the queue is full,
connect()returnsECONNREFUSEDimmediately. Since there is no network delay or packet loss on a local machine, retrying instantly is unlikely to succeed, so the kernel reports the error right away.
4. accept and Client Identity
When a server calls accept(), it returns a new file descriptor for the connection.
- If the client called
bind()before connecting,accept()returns the client’s pathname in the second argument. - If the client did not bind (which is common for clients), the returned address length is usually 0, indicating an “unnamed” client.