What is a Socket?
A socket is a communication endpoint. Think of it like a power socket on a wall โ two devices plug into it and exchange electricity (data). In Linux, a socket is a special file descriptor that lets two processes exchange data, whether they are on the same machine or across a network.
Sockets were introduced in BSD Unix in the early 1980s and are now the standard way to do network programming on Linux. The Linux sockets API follows the POSIX standard and is compatible with BSD sockets.
Every socket belongs to a communication domain. The domain determines:
- Where the communication happens (same machine or across a network)
- What address format is used to identify the socket
| Domain Constant | Address Format | Use Case |
|---|---|---|
AF_UNIX (also AF_LOCAL) |
Filesystem pathname | IPC on the same Linux machine |
AF_INET |
IPv4 address + port number | Network communication over IPv4 |
AF_INET6 |
IPv6 address + port number | Network communication over IPv6 |
AF stands for “Address Family”. You will also see PF_UNIX, PF_INET etc. (PF = Protocol Family). In Linux these are identical values โ use AF_* in your code as recommended by POSIX.
Within a domain, there are different socket types that control how data flows between two sockets. The two most important types are:
- Connection-oriented
- Reliable delivery (no data loss)
- Data arrives in order
- Byte-stream (no message boundaries)
- Bidirectional
- Uses TCP in AF_INET
- Connectionless
- Unreliable (packets may be lost)
- No guaranteed ordering
- Message boundaries preserved
- Bidirectional
- Uses UDP in AF_INET
The combination of domain + type uniquely defines the communication protocol. For example: AF_INET + SOCK_STREAM = TCP and AF_INET + SOCK_DGRAM = UDP.
Once a socket connection is set up, you can read and write data on it just like a regular file, because sockets are file descriptors in Linux. You have two choices:
Use read() and write() system calls โ same as for files and pipes.
Use send(), recv(), sendto(), recvfrom() โ these offer extra flags and features not available with standard I/O.
By default, these calls block if data is not yet available. To make them non-blocking, use fcntl() with the O_NONBLOCK flag.
On Linux, you can also check how many bytes are waiting to be read using:
int cnt;
ioctl(fd, FIONREAD, &cnt);
/* cnt now holds unread byte count */
For a stream socket this gives total unread bytes. For a datagram socket it gives the size of the next waiting datagram (or 0 if none pending).
Linux provides many IPC (Inter-Process Communication) mechanisms. Sockets are the most powerful because they work both locally and across the network.
| IPC Mechanism | Same Machine | Across Network | Bidirectional |
|---|---|---|---|
| Pipe | โ | โ | โ (one-way) |
| FIFO | โ | โ | โ (one-way) |
| Message Queue | โ | โ | โ |
| Shared Memory | โ | โ | โ |
| Socket (AF_UNIX) | โ | โ | โ |
| Socket (AF_INET) | โ | โ | โ |
AF_UNIX (also called AF_LOCAL) sockets communicate between processes on the same machine using filesystem pathnames as addresses. AF_INET sockets communicate over an IPv4 network using IP address + port number. AF_UNIX is faster (no network stack overhead) but cannot cross machine boundaries.
SOCK_STREAM provides a reliable, connection-oriented, ordered byte stream (TCP). SOCK_DGRAM provides unreliable, connectionless, message-boundary-preserving communication (UDP). Stream sockets require a connection setup phase; datagram sockets do not.
read()/write(). The socket-specific send()/recv() calls add extra functionality via a flags parameter (e.g., MSG_DONTWAIT, MSG_PEEK, MSG_WAITALL) that is not available with standard I/O calls.
AF_* constants in socket() calls. Historically PF was intended for protocol selection and AF for address, but in practice there is always a 1:1 mapping, so AF_* is universally used.
ioctl(fd, FIONREAD, &cnt). For stream sockets it returns total unread bytes. For datagram sockets it returns the size of the next datagram. Alternatively, recv() with the MSG_PEEK flag reads data without removing it from the buffer.
Learn how to create sockets, understand the arguments, and use the new kernel flags.
