keepcalculator

06 Numbers and Powers

Unix Domain Socket: Which Type and Address to Choose

Card No. 06·38744 · Updated · Standard formula, shown below

For Unix domain sockets, choose stream sockets (SOCK_STREAM) with a filesystem path address for nearly all client-server applications, and use datagram sockets (SOCK_DGRAM) with a filesystem path only when you need message boundaries and can tolerate loss. This combination gives you reliable, ordered, connection-oriented communication with standard file permissions, which is what most programs expect.

Background: What Are Unix Domain Sockets?

Unix domain sockets (UDS) are an inter-process communication (IPC) mechanism that allows processes on the same host to exchange data. Unlike TCP/IP sockets, which use IP addresses and ports, UDS use filesystem paths or abstract names as addresses. They were introduced in early Unix systems and remain a core part of modern operating systems like Linux, macOS, and BSD variants. UDS are often used by databases (e.g., PostgreSQL), web servers (e.g., Nginx), and system services because they are faster than TCP/IP for local communication—no network stack overhead, no routing, and no firewall checks.

Socket Types: Stream, Datagram, and Sequenced

Unix domain sockets support three main types, each with different semantics:

  • SOCK_STREAM – Provides a reliable, ordered, byte-stream connection, similar to TCP. Data is delivered in order, without message boundaries. Use this for most client-server applications where you want a continuous flow of data (e.g., HTTP, database protocols).
  • SOCK_DGRAM – Provides message-oriented, unreliable communication, similar to UDP. Each send() call creates a distinct message, and messages can be lost or reordered. Use this when you need message boundaries and can handle loss (e.g., logging, syslog).
  • SOCK_SEQPACKET – Provides reliable, ordered, message-oriented communication. Each message is preserved as a unit, but delivery is guaranteed. This is a hybrid that is less commonly used but useful for protocols that need both reliability and message boundaries.

In practice, SOCK_STREAM is the default choice for most applications because it offers the same interface as TCP, making it easy to port network code. SOCK_DGRAM is useful for lightweight, one-shot messages where you don’t want the overhead of a connection.

Address Types: Filesystem Path vs. Abstract Namespace

Unix domain socket addresses come in two flavors:

  • Filesystem path – A normal file path like /var/run/mysocket.sock. The socket appears as a file in the filesystem, and you can control access with standard file permissions (owner, group, others). This is the most portable and widely used address type. However, the file remains on disk even after the socket is closed, so you need to unlink it manually if you want to reuse the same path.
  • Abstract namespace – A name that is not tied to the filesystem, starting with a null byte (e.g., \0myapp). This is Linux-specific. Abstract sockets have no file entry, so they don’t leave stale files, and they don’t require filesystem permissions. They are automatically cleaned up when the socket is closed. However, they are not portable to other Unix-like systems and cannot be accessed via normal file tools (like ls).

For most applications, a filesystem path is the better choice because it is portable, familiar, and allows fine-grained access control. Use abstract sockets only when you are on Linux and need to avoid filesystem clutter or when you want to prevent accidental collisions with existing files.

How to Choose: Practical Guidelines

Here is a step-by-step approach to selecting the right type and address:

  1. Determine the communication pattern: If you need a continuous, reliable stream of bytes, choose SOCK_STREAM. If you need discrete messages and can handle loss, choose SOCK_DGRAM. If you need both reliability and message boundaries, choose SOCK_SEQPACKET.
  2. Consider portability: If your application may run on multiple Unix-like systems (Linux, macOS, BSD), use a filesystem path. Abstract namespace is Linux-only.
  3. Think about permissions: If you need to restrict which users can connect, use a filesystem path and set appropriate permissions (e.g., chmod 660). Abstract sockets do not support file permissions.
  4. Check for stale files: If you use a filesystem path, ensure your application unlinks the socket file on shutdown, or use a unique path per run (e.g., include the PID). Otherwise, you may get a “Address already in use” error.
  5. Test performance: For high-throughput local IPC, SOCK_STREAM is generally faster than SOCK_DGRAM because it uses a larger buffer and avoids per-message overhead. But measure in your specific scenario.

Common Pitfalls and Misconceptions

One common mistake is assuming that Unix domain sockets are only for local communication—they are, but that is their strength. Another misconception is that SOCK_DGRAM over UDS is as unreliable as UDP over IP; in practice, on Linux, UDS datagrams are not lost unless the receive buffer is full, and they are always delivered in order. However, they can be dropped if the buffer overflows, so you should still handle loss.

Another pitfall is forgetting to unlink the socket file before rebinding. If your program crashes and leaves the socket file, the next run will fail with EADDRINUSE. A common workaround is to unlink the path at startup, but be careful: if another process is still using the socket, unlinking it will cause that process to lose its endpoint. A safer approach is to use a unique path per instance or use abstract sockets.

Also, be aware of the maximum path length for filesystem sockets. On Linux, the limit is 108 characters, including the null terminator. If your path is longer, the bind() call will fail with ENAMETOOLONG.

Comparison: Unix Domain Sockets vs. TCP/IP Localhost

When communicating between processes on the same machine, you have two main options: Unix domain sockets or TCP/IP over the loopback interface (127.0.0.1). Here is a comparison:

  • Performance: UDS are generally faster because they bypass the network stack entirely. They avoid IP/TCP header processing, checksum calculations, and routing. For high-frequency IPC, UDS can be 2-3 times faster than loopback TCP.
  • Security: UDS with filesystem paths allow you to control access via file permissions. TCP loopback is accessible to any local process, unless you use firewall rules (which are complex and often not configured).
  • Portability: TCP loopback works on any system with an IP stack, including Windows. UDS are Unix-specific (though Windows 10+ has a similar feature called AF_UNIX, but not all applications support it).
  • Debugging: TCP loopback can be inspected with tools like netstat or ss; UDS can be inspected with ss -x or lsof. Both are manageable.

In summary, for local IPC on Unix-like systems, UDS are the preferred choice for performance and security. TCP loopback is a fallback when you need portability or when you are already using TCP in your application.

Security and Permissions

When using a filesystem path, you can set the socket file’s permissions to restrict access. The socket file is created by the server process, so you can set the umask or explicitly call chmod after binding. For example, to allow only the owner and group to connect, use chmod 660. This is a simple and effective way to secure local IPC.

Abstract sockets do not have file permissions, so any process running as the same user (or root) can connect. If you need to restrict access, you must implement authentication in your protocol, which is more complex. Therefore, for security-sensitive applications, prefer a filesystem path with restrictive permissions.

Another consideration is the directory where the socket file resides. Ensure that the directory itself has appropriate permissions so that unauthorized users cannot delete or replace the socket file (a symlink attack). For example, use a directory like /var/run/app with 755 permissions and the socket file with 660.

Frequently Asked Questions

Q: Can I use a Unix domain socket with a relative path?
Yes, you can use a relative path, but it is not recommended because it depends on the current working directory of the process. This can lead to confusion and security issues. Always use an absolute path for clarity and consistency.

Q: What is the difference between SOCK_DGRAM and SOCK_SEQPACKET?
SOCK_DGRAM is message-oriented but unreliable; messages can be lost if the buffer overflows. SOCK_SEQPACKET is also message-oriented but reliable and preserves order. Use SOCK_SEQPACKET when you need both message boundaries and guaranteed delivery, but note that not all systems support it (Linux does, macOS does not).

Q: How do I remove a stale socket file?
You can unlink it with rm /path/to/socket or in code with unlink(). However, be sure that no process is still using it. A common pattern is to unlink the path at the start of the server, but only if you are certain no other instance is running.

Q: Can I use Unix domain sockets over a network?
No, Unix domain sockets are strictly local to the host. For network communication, you need TCP/IP or other network protocols.

Q: What is the maximum size of a datagram for SOCK_DGRAM over UDS?
The maximum datagram size is limited by the system’s socket buffer. On Linux, the default is around 208 KB, but you can increase it with SO_SNDBUF and SO_RCVBUF. However, very large datagrams may be inefficient; consider using SOCK_STREAM for large data.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →