1. Overview
A socket is an abstraction for a communication endpoint. The well-known socket command can be used for both Internet domain sockets and Unix domain sockets. Internet domain sockets provide a communication mechanism between processes on different machines. However, Unix domain sockets are for communication among processes on the same machine.
There are many libraries in different programming languages for using the socket API (Application Programming Interface). The socket module in the Python programming language is an example.
In this tutorial, we’ll focus on Unix domain sockets and discuss how to create and use them using the command-line tools that Linux provides.
2. Unix Domain Sockets
A Unix domain socket is an IPC (inter-process communication) mechanism providing communication between processes running on the same machine. They’re also known as named sockets. Although Internet domain sockets can be used for the same purpose, using Unix domain sockets is more efficient as they bypass the overhead of network layers. Unix domain sockets just copy data within the kernel of the operating system.
Unix domain sockets provide communication by using both stream and datagram socket interfaces. The stream socket type facilitates the usage of sequenced, bidirectional, and connection-oriented byte streams, whereas the datagram socket type provides fixed-length, connectionless messages. However, unlike Internet datagram sockets, Unix datagram sockets are reliable.
3. Using nc
We can use the nc command to communicate using Unix domain sockets:
$ nc -lU /tmp/my.sock
The -U option of nc specifies Unix domain sockets as the underlying communication method. The -l option is used to listen for incoming connections. It also creates the Unix Domain socket passed as an argument. The name of the socket file is /tmp/my.sock in our example.
Let’s check the existence of /tmp/my.sock after running nc -lU /tmp/my.sock using the file command:
$ file /tmp/my.sock
/tmp/my.sock: socket
The file exists and its type is socket as expected.
Now, let’s start a second instance of nc in another terminal by passing the name of the same socket file as an argument:
$ nc -U /tmp/my.sock
We don’t need to pass the -l option as we’ve already created the socket file. Now, both processes are waiting for communication using the socket file.
Let’s write a message in the first terminal and send it by pressing Enter:
$ nc -lU /tmp/my.sock
Hello Baeldung
Let’s check the second terminal:
$ nc -U /tmp/my.sock
Hello Baeldung
The message was received by the second process. Now, let’s send another message from the second terminal:
$ nc -U /tmp/my.sock
Hello Baeldung
Hi Baeldung once more!
The first process receives this message as expected:
$ nc -lU /tmp/my.sock
Hello Baeldung
Hi Baeldung once more!
Therefore, we have two nc processes communicating with each other using Unix domain sockets.
The -U option of nc uses stream sockets by default. We can check the socket type using the ss command:
$ ss -xa | grep my.sock
u_str ESTAB 0 0 /tmp/my.sock 53429 * 51745
The ss command is useful for investigating sockets. Its -x option displays Unix domain sockets. The -a option lists both listening and non-listening sockets. We use grep my.sock to filter the output of ss -xa. u_str in the output means that this is a stream socket.
It’s also possible to use datagram sockets. In this case, we must pass the -u option in addition to the other options:
$ nc -lUu /tmp/my.sock
$ nc -Uu /tmp/my.sock
Next, we run the ss -xa command:
$ ss -xa | grep my.sock
u_dgr UNCONN 0 0 /tmp/my.sock 54743 * 55374
u_dgr in the output means that this is a datagram socket.
4. Using socat
Another option for communication with Unix domain sockets is to use the socat command. The socat command establishes a bidirectional communication channel between two data sources and transfers data between them. It supports Unix domain sockets in addition to many other types of addresses.
Let’s spawn a process using socat:
$ socat - UNIX-LISTEN:/tmp/my.sock
This command is equivalent to nc -lU /tmp/my.sock. The UNIX-LISTEN address type is for listening on a socket file, which is /tmp/my.sock in our case, using a Unix domain stream socket. It creates the socket file if it doesn’t exist.
socat expects two addresses as arguments. The hyphen (-) in the command is a synonym for STDIO. In other words, it specifies that messages should be read from STDIN and that incoming messages should be written to STDOUT. This is the first address. The second address is UNIX-LISTEN:/tmp/my.sock. Therefore, the established communication channel is between STDIO and UNIX-LISTEN:/tmp/my.sock.
We can change the order of the addresses as the communication channel is bidirectional, thus, we can use socat UNIX-LISTEN:/tmp/my.sock – instead of socat – UNIX-LISTEN:/tmp/my.sock.
Now, let’s spawn another process using socat:
$ socat - UNIX-CONNECT:/tmp/my.sock
The UNIX-CONNECT address type connects to the specified UNIX domain stream socket, which is /tmp/my.sock in our case.
Both processes wait to send and receive messages using the socket file, similar to the usage of nc.
socat also supports communication with Unix domain datagram sockets. We can use the UNIX-RECVFROM and UNIX_SENDTO address types in this case.
5. Using socket
Another option for using Unix domain sockets is the socket command. The socket command creates a TCP or Unix domain socket and connects to standard input and output. It’s available only in some Linux distros such as Ubuntu and Debian. However, it supports only Unix domain stream sockets.
Let’s create one end of the communication channel using socket:
$ socket -s /tmp/my.sock
The -s option of socket creates a server socket and waits for incoming connections. It takes the socket file as an argument. We can create the other end of the Unix domain stream socket using the same command without the -s option:
$ socket /tmp/my.sock
Sending and receiving messages is similar to the usage of nc.
6. Conclusion
In this article, we discussed how to create and use Unix domain sockets from the command line. We learned about the usage of the nc, socat, and socket utilities. nc and socat support both Unix domain stream sockets and Unix domain datagram sockets. However, socket supports only Unix domain stream sockets.