Below is a step‑by‑step, ordered list of the POSIX functions you normally call when you work with a Unix‑domain (AF_LOCAL / AF_UNIX) stream socket (SOCK_STREAM).
I split the list into two sections – one for the server side and one for the client side – because the order of calls differs slightly.
| # | Function (header) | What it does | Typical usage notes |
|---|---|---|---|
| 1 | socket(int domain, int type, int protocol) #include <sys/socket.h> |
Creates a new socket descriptor. | domain = AF_LOCAL (or AF_UNIX), type = SOCK_STREAM, protocol = 0. |
| 2 | unlink(const char *pathname) #include <unistd.h> |
Removes a stale socket‑file name if it already exists. | Do this before bind() so bind() won’t fail with EADDRINUSE. |
| 3 | bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) #include <sys/socket.h> |
Associates the socket with a pathname in the filesystem. | addr points to a struct sockaddr_un whose sun_path holds the file name. |
| 4 | listen(int sockfd, int backlog) #include <sys/socket.h> |
Marks the socket as a passive (listening) socket. | backlog is the maximum number of pending connections (e.g., 5‑10). |
| 5 | accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) #include <sys/socket.h> |
Blocks (or returns immediately if non‑blocking) until a client connects, returning a new connected socket descriptor. | Use the returned descriptor for all I/O with that client. |
| 6 | (optional) getsockname(), getpeername() |
Retrieve local or peer address info (mostly for debugging). | |
| 7 | read() / recv() #include <unistd.h> / <sys/socket.h> |
Receive data from the connected client. | For stream sockets you can treat them as regular file descriptors. |
| 8 | write() / send() |
Send data to the client. | |
| 9 | (optional) shutdown(int sockfd, int how) #include <sys/socket.h> |
Gracefully close one or both directions of the connection (SHUT_RD, SHUT_WR, SHUT_RDWR). |
|
| 10 | close(int fd) #include <unistd.h> |
Release the socket descriptor. | |
| 11 | unlink(const char *pathname) (again) |
Remove the socket file from the filesystem when the server terminates. |
Typical server flow (pseudo‑code)
int listen_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
unlink("/tmp/my_socket"); // step 2
struct sockaddr_un addr = {0};
addr.sun_family = AF_LOCAL;
strcpy(addr.sun_path, "/tmp/my_socket");
bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)); // step 3
listen(listen_fd, 10); // step 4
while (1) {
int conn_fd = accept(listen_fd, NULL, NULL); // step 5
// … read/write on conn_fd …
close(conn_fd); // step 10
}
close(listen_fd);
unlink("/tmp/my_socket"); // step 11| # | Function (header) | What it does | Typical usage notes |
|---|---|---|---|
| 1 | socket(int domain, int type, int protocol) |
Creates a new socket descriptor. | Same arguments as the server. |
| 2 | connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) |
Initiates a connection to the server’s socket file. | addr is a struct sockaddr_un with the same pathname the server bound to. |
| 3 | write() / send() |
Send request/data to the server. | |
| 4 | read() / recv() |
Receive response/data from the server. | |
| 5 | (optional) shutdown(int sockfd, int how) |
Gracefully close one or both directions. | |
| 6 | close(int fd) |
Release the socket descriptor. |
Typical client flow (pseudo‑code)
int sock = socket(AF_LOCAL, SOCK_STREAM, 0); // step 1
struct sockaddr_un addr = {0};
addr.sun_family = AF_LOCAL;
strcpy(addr.sun_path, "/tmp/my_socket");
connect(sock, (struct sockaddr *)&addr, sizeof(addr)); // step 2
write(sock, "Hello", 5); // step 3
char buf[256];
int n = read(sock, buf, sizeof(buf)); // step 4
/* … process … */
close(sock); // step 6| Function | Header | Why it’s useful in this context |
|---|---|---|
fcntl() |
<fcntl.h> |
Set the socket non‑blocking (O_NONBLOCK) before accept()/connect(). |
setsockopt() |
<sys/socket.h> |
Tune options like SO_REUSEADDR (rarely needed for AF_LOCAL) or SO_RCVBUF / SO_SNDBUF. |
getsockopt() |
<sys/socket.h> |
Query current socket options. |
select() / poll() / epoll() |
<sys/select.h>, <poll.h>, <sys/epoll.h> |
Multiplex I/O when handling many client connections. |
socketpair() |
<sys/socket.h> |
Quickly create a pair of connected AF_LOCAL stream sockets (useful for intra‑process communication). |
chmod() / chown() |
<sys/stat.h> |
Adjust permissions of the socket file after bind() if you need restricted access. |
unlinkat() |
<fcntl.h> |
Same as unlink() but works with a directory file descriptor (useful in sandboxed environments). |
Server: socket → unlink (old) → bind → listen → accept → (read/write) → close → unlink (final)
Client: socket → connect → (write/read) → close
Feel free to ask if you need a concrete C example, a Python wrapper, or details on error handling for any of these calls!