Sockets are a way to enable inter-process communication between programs running on a server, or between programs running on separate servers. Communication between servers relies on network sockets, which use the Internet Protocol (IP) to encapsulate and handle sending and receiving data.
Network sockets on both clients and servers are referred to by their socket address. An address is a unique combination of a transport protocol like the Transmission Control Protocol (TCP) or User Datagram Protocol (UDP), an IP address, and a port number.
In this tutorial you will learn about the following different types of sockets that are used for inter-process communication:
In each section of this tutorial you will also learn how to enumerate the respective socket types on a Linux system. You’ll examine each type of socket using a variety of command line tools.
The examples in this tutorial were validated on an Ubuntu 20.04 server. You can follow this tutorial using most modern Linux distributions on a local computer or remote server, as long as you have the equivalent version of each of the required tools for your distribution installed.
To get started using Ubuntu 20.04, you will need one server that has been configured by following our Initial Server Setup for Ubuntu 20.04 guide.
You will also need a few other packages in order to examine sockets on your system. Ensure that your system’s package cache is up to date using the apt update
command:
- sudo apt update
Then install the required packages using this command:
- sudo apt install iproute2 netcat-openbsd socat
The iproute2
package contains the ss
utility, which is what we’ll use to inspect sockets. We’ll use the netcat-openbsd
package to install netcat. Note that netcat is abbreviated to nc
when it is invoked on the command line. Finally, we’ll use the socat
package to create example sockets.
Stream sockets are connection oriented, which means that packets sent to and received from a network socket are delivered by the host operating system in order for processing by an application. Network based stream sockets typically use the Transmission Control Protocol (TCP) to encapsulate and transmit data over a network interface.
TCP is designed to be a reliable network protocol that relies on a stateful connection. Data that is sent by a program using a TCP-based stream socket will be successfully received by a remote system (assuming there are no routing, firewall, or other connectivity issues). TCP packets can arrive on a physical network interface in any order. In the event that packets arrive out of order, the network adapter and host operating system will ensure that they are reassembled in the correct sequence for processing by an application.
A typical use for a TCP-based stream socket would be for a web server like Apache or Nginx handling HTTP requests on port 80
, or HTTPS on port 443
. For HTTP, a socket address would be similar to 203.0.113.1:80
, and for HTTPS it would be something like 203.0.113.1:443
.
In the following example you’ll use the socat
(short for SOcket CAT
) command to emulate a web server listening for HTTP requests on port 8080 (the alternative HTTP port). Then you’ll examine the socket using the ss
, and nc
commands.
First, run the following socat
commands to create two TCP-based sockets that are listening for connections on port 8080
, using IPv4 and IPv6 interfaces:
- socat TCP4-LISTEN:8080,fork /dev/null&
- socat TCP6-LISTEN:8080,ipv6only=1,fork /dev/null&
TCP4-LISTEN:8080
and TCP6-LISTEN:8080
arguments are the protocol type and port number to use. They tell socat
to create TCP sockets on port 8080
on all IPv4 and IPv6 interfaces, and to listen to each socket for incoming connections. socat
can listen on any available port on a system, so any port from 0
to 65535
is a valid parameter for the socket option.fork
option is used to ensure that socat
continues to run after it handles a connection, otherwise it would exit automatically./dev/null
path is used in place of a remote socket address. In this case it tells socat
to print any incoming input to the /dev/null
file, which discards it silently.ipv6only=1
flag is used for the IPv6 socket to tell the operating system that the socket is not configured to send packets to IPv4-mapped IPv6 addresses. Without this flag, socat
will bind to both IPv4 and IPv6 addresses.&
character instructs the shell to run the command in the background. This flag will ensure that socat
continues to run while you invoke other commands to examine the socket.You will receive output like the following, which indicates the two socat
process IDs that are running in the background of your shell session. Your process IDs will be different than the ones highlighted here:
Output[1] 434223
[2] 434224
Now that you have two socat
processes listening on TCP port 8080
in the background, you can examine the sockets using the ss
and nc
utilities.
To examine TCP sockets on a modern Linux system using the ss
command, run it with the following flags to restrict the output:
-4
and -6
flags tell ss
to only examine IPv4 or IPv6 sockets respectively. Omitting this option will display both sets of sockets.t
flag limits the output to TCP sockets. By default the ss
tool will display all types of sockets in use on a Linux system.l
flag limits the output to listening sockets. Without this flag, all TCP connections would be displayed, which would include things like SSH, clients that may be connected to a web-server, or connections that your system may have to other servers.n
flag ensures that port numbers are displayed instead of service names.First run the ss -4 -tln
command to examine the IPv4 TCP-based sockets that are listening for connections on your system:
- ss -4 -tln
You will receive output like the following:
OutputState Recv-Q Send-Q Local Address:Port Peer Address:Port Process
. . .
LISTEN 0 1 0.0.0.0:8080 0.0.0.0:*
. . .
There may be other lines with other ports in your output depending on which services are running on your system. The highlighted 0.0.0.0:8080
portion of the output indicates the IPv4 TCP socket is listening on all available IPv4 interfaces on port 8080
. A service that is only listening on a specific IPv4 address will show only that IP in the highlighted field, for example 203.0.113.1:8080
.
Now run the same ss
command again but with the -6
flag:
- ss -6 -tln
You will receive output like the following:
OutputState Recv-Q Send-Q Local Address:Port Peer Address:Port Process
. . .
LISTEN 0 5 [::]:8080 [::]:*
. . .
There may be other lines with other ports in your output depending on which services are running on your system. The highlighted [::]:8080
portion of the output indicates the IPv6 TCP socket is listening on all available IPv6 interfaces on port 8080
(as indicated by the ::
characters, which are IPv6 notation for an address composed of all zeros). A service that is only listening on a specific IPv6 address will show only that IP in the highlighted field, for example [2604:a880:400:d1::3d3:6001]:8080
.
So far you have learned how to create and enumerate TCP sockets on both IPv4 and IPv6 interfaces. Now that you have two sockets listening for connections, you can experiment with connecting to sockets using the netcat utility.
Using netcat to test TCP connections to local and remote sockets is a very useful troubleshooting technique that can help isolate connectivity and firewall issues between systems.
To connect to the IPv4 socket over the local loopback address using netcat, run the following command:
- nc -4 -vz 127.0.0.1 8080
-4
flag tells netcat to use IPv4.-v
flag is used to print verbose output to your terminal.z
option ensures that netcat only connects to a socket, without sending any data.127.0.0.1
IP address is used since your system will have its own unique IP address. If you know the IP for your system you can test using that as well. For example, if your system’s public or private IP address is 203.0.113.1 you could use that in place of the loopback IP.You will receive output like the following:
OutputConnection to 127.0.0.1 (127.0.0.1) 8080 port [tcp/http-alt] succeeded!
The highlighted line is the output from netcat. It indicates that netcat connected to the TCP socket listening on the loopback 127.0.0.1
IPv4 address on port 8080
. You can ignore the second line, it is from the socat process running in the background in your terminal.
Now you can repeat the same connection test but using IPv6. Run the following netcat command:
- nc -6 -vz ::1 8080
You should receive output like the following:
OutputConnection to ::1 8080 port [tcp/http] succeeded!
The highlighted line is the output from netcat. It indicates that netcat connected to the TCP socket listening on the loopback ::1
IPv6 address on port 8080
. Again, you can ignore the second line of output.
To clean up your sockets, you’ll need to run the fg
(foreground) command for each socat process that you created. Then you’ll use CTRL+C
to close each socat. fg
will bring processes to the foreground of your terminal in the reverse order that you ran them, so when you run it, the second socat
instance will be the one that you interact with first.
Run fg
to bring the second IPv6 socat instance to the foreground of your terminal. Then run CTRL+C
to close it.
- fg
You will receive output like the following:
Outputsocat TCP6-LISTEN:8080,ipv6only=1,fork /dev/null
Press CTRL+C
to stop the process.
Now run fg
again to clean up the first IPv4 socket. You should have output like the following:
Outputsocat TCP4-LISTEN:8080,fork /dev/null
Press CTRL+C
to stop the process.
You have now created, examined, and connected to IPv4 and IPv6 sockets on your system. These techniques and tools will work on local development systems, or remote production servers, so try experimenting with each tool to become more familiar with how they can be used to test and troubleshoot TCP sockets.
Datagram sockets are connectionless, which means that packets sent and received from a socket are processed individually by applications. Network-based datagram sockets typically use the User Datagram Protocol (UDP) to encapsulate and transmit data.
UDP does not encode sequence information in packet headers, and there is no error correction built into the protocol. Programs that use datagram-based network sockets must build in their own error handling and data ordering logic to ensure successful data transmission.
UDP sockets are commonly used by Domain Name System (DNS) servers. By default, DNS servers use port 53
to send and receive queries for domain names. An example UDP socket address for a DNS server would be similar to 203.0.113.1:53
.
Note: Although the protocol is not included in the human-readable version of the socket address, operating systems differentiate socket addresses by including TCP and UDP protocols as part of the address. So a human-readable socket address like 203.0.113.1:53
could be using either protocol. Tools like ss
, and the older netstat
utility, are used to determine which kind of socket is being used.
The Network Time Protocol (NTP) uses a UDP socket on port 123
to synchronize clocks between computers. An example UDP socket for the NTP protocol would be 203.0.113.1:123
.
As in the previous TCP socket example, in this section you’ll use socat
again to emulate an NTP server listening for requests on UDP port 123
. Then you’ll examine the sockets that you create using the ss
and nc
commands.
First, run the following socat
commands to create two UDP sockets that are listening for connections on port 123, using IPv4 and IPv6 interfaces:
- sudo socat UDP4-LISTEN:123,fork /dev/null&
- sudo socat UDP6-LISTEN:123,ipv6only=1,fork /dev/null&
You will receive output like the following, which indicates the two socat
process IDs that are running in the background of your shell session. Your process IDs will be different than the ones highlighted here:
Output[1] 465486
[2] 465487
sudo
, because ports 0
to 1024
are reserved on most systems. sudo
runs a command with administrator permissions, which allows socat
to bind to any port in the reserved range.UDP4-LISTEN:123
and UDP6-LISTEN:123
arguments are the protocol type and port to use. They tell socat to create UDP based sockets on port 123
on both IPv4 and IPv6 interfaces, and to listen for incoming data. Again any port in the entire range of 0-65535 is a valid parameter for UDP sockets.fork
, ipv6only=1
, and /dev/null
arguments are used in the same manner as described in the previous TCP example.Now that you have two socat
processes listening on UDP port 123
, you can examine the sockets using the ss
and nc
utilities.
To examine UDP sockets on a modern Linux system using the ss
command, run it with the following -4
, -6, and
uln` flags to restrict the output:
The u
flag limits the output to UDP sockets.
The other flags are the same as the ones used in the previous TCP example.
First run the ss -4 -uln
command to examine the IPv4 UDP sockets that are listening for connections on your system:
- ss -4 -uln
You will receive output like the following:
OutputState Recv-Q Send-Q Local Address:Port Peer Address:Port Process
. . .
UNCONN 0 0 0.0.0.0:123 0.0.0.0:*
. . .
There may be other lines with other ports in your output depending on which services are running on your system. The highlighted 0.0.0.0:123
portion of the output indicates the IPv4 UDP socket is available on all IPv4 interfaces on port 123
. A service that is only available on a specific IPv4 address will show only that IP in the highlighted field, for example 203.0.113.1:123
.
Now run the same ss
command again but with the -6
flag:
- ss -6 -uln
You will receive output like the following:
OutputState Recv-Q Send-Q Local Address:Port Peer Address:Port Process
. . .
UNCONN 0 0 [::]:123 [::]:*
. . .
There may be other lines with other ports in your output depending on which services are running on your system. The highlighted [::]:123
portion of the output indicates the IPv6 TCP socket is available on all IPv6 interfaces on port 123
(as indicated by the ::
characters). A service that is only available on a specific IPv6 address will show only that IP in the highlighted field, for example [2604:a880:400:d1::3d3:6001]:123
.
Now that you are familiar with how to create and enumerate UDP sockets on both IPv4 and IPv6 interfaces, you can experiment with connecting to them. As with TCP sockets, you can experiment with UDP sockets using the netcat utility.
To connect to the example UDP socket on port 123
that you created in the previous section of this tutorial, run the following netcat command:
- nc -4 -u -vz 127.0.0.1 123
-4
flag tells netcat to use IPv4.-u
option instructs netcat to use UDP instead of TCP.-v
flag is used to print verbose output to your terminal.z
option ensures that netcat only connects to a socket, without sending any data.127.0.0.1
IP address is used since your system will have its own unique IP address. If you know the IP for your system you can test using that as well. For example, if your system’s public or private IP address is 203.0.113.1
you could use that in place of the loopback IP.You will receive output like the following:
OutputConnection to 127.0.0.1 123 port [udp/ntp] succeeded!
The output indicates that netcat did not receive an error from the UDP socket listening on the loopback 127.0.0.1
IPv4 address on port 123
. This lack of an error response is used to infer that the socket at 127.0.0.1:123
is available. This behaviour is different from TCP sockets, which need to exchange packets to confirm if a socket is available.
Note: If the socket in this example was unavailable, the remote system would return an ICMP type 3 message (Destination Unreachable) with a Code of 3, indicating that the port is unreachable on the remote host.
Inferring that a socket is available based on a lack of error response assumes that there are no firewalls or connectivity issues that are blocking ICMP traffic. Without sending, receiving, and verifying application data over a UDP socket, there is no guarantee that a remote UDP port is open and accepting packets.
Now you can repeat the same connection test but using IPv6. Run the following netcat command:
- nc -6 -u -vz ::1 123
You should receive output like the following:
OutputConnection to ::1 123 port [udp/ntp] succeeded!!
The output indicates that netcat did not receive an error from the UDP socket listening on the loopback ::1
IPv6 address on port 123
. Again, this lack of an error response is used to infer that the socket at ::1:123
is available.
To clean up your sockets, you’ll need to run the fg
(foreground) command for each socat process that you created. Then you’ll use CTRL+C
to close each socat.
Run fg
to bring the second IPv6 socat
instance to the foreground of your terminal. Then run CTRL+C
to close it.
- fg
You will receive output like the following:
Outputsudo socat UDP6-LISTEN:123,ipv6only=1,fork /dev/null
Press CTRL+C
to stop the process.
Now run fg
again to clean up the first IPv4 socket. You will have output like the following:
Outputsudo socat UDP4-LISTEN:123,fork /dev/null
Press CTRL+C
to stop the process.
You have now created, examined, and tested IPv4 and IPv6 UDP sockets on your system. Try experimenting with each tool to become more familiar with how they can be used to test and troubleshoot UDP sockets.
Programs that run on the same server can also communicate with each other using Unix Domain Sockets (UDS). Unix Domain Sockets can be stream-based, or datagram-based. When using domain sockets, data is exchanged between programs directly in the operating system’s kernel via files on the host filesystem. To send or receive data using domain sockets, programs read and write to their shared socket file, bypassing network based sockets and protocols entirely.
Unix Domain Sockets are used widely by database systems that do not need to be connected to a network interface. For example, MySQL on Ubuntu defaults to using a file named /var/run/mysqld/mysql.sock
for communication with local clients. Clients read from and write to the socket, as does the MySQL server itself.
PostgreSQL is another database system that uses a socket for local, non-network communication. Typically it defaults to using /run/postgresql/.s.PGSQL.5432
as its socket file.
In the previous sections you explored how TCP is used with stream sockets, and how UDP is used with datagram sockets. In this section you’ll use socat
to create both stream-based and datagram-based Unix Domain Sockets without using TCP or UDP to encapsulate data to send over networks. Then you’ll examine the sockets that you create using the ss
, and nc
commands. Finally, you’ll learn about testing Unix Domain Sockets using netcat.
To get started, run the following socat
commands to create two socket files:
- socat unix-listen:/tmp/stream.sock,fork /dev/null&
- socat unix-recvfrom:/tmp/datagram.sock,fork /dev/null&
unix-listen
address type, which will create a stream-based UDS.unix-recvfrom
as the socket type, which will create a datagram-based UDS:
separator. The filename is the address of the socket itself. For the first stream example it is /tmp/stream.sock
and for the second datagram example it is /tmp/datagram.sock
. Note that the name of a socket is arbitrary but it helps if it is descriptive when you are troubleshooting.fork
, and /dev/null
arguments are used in the same manner as described in the Stream and Datagram socket example sections.Now that you have created your two UDS sockets, you can examine them using the ss
and nc
utilities.
To list all listening Unix Domain Sockets, run the ss -xln
command. The x
flag ensures that only domain sockets are displayed.
- ss -xln
You will receive output like the following:
OutputNetid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
. . .
u_str LISTEN 0 5 /tmp/stream.sock 436470 * 0
u_dgr UNCONN 0 0 /tmp/datagram.sock 433843 * 0
. . .
Notice the highlighted u_str
portion of the /tmp/stream/sock
line. This field indicates that the socket type is a stream-based UDS. The second line shows the type is u_dgr
which means the socket type is datagram-based.
Since Unix Domain Sockets are files, the usual Linux user and group permissions and access controls can be used to restrict who can connect to the socket. You can also use filesystem tools like ls
, mv
, chown
and chmod
to examine and manipulate UDS files. Tools like SELinux can also be used to label UDS files with different security contexts.
To check if a file is a UDS socket, use the ls
, file
or stat
utilities. However, it is important to note that none of these tools can determine if a UDS is stream or datagram-based. Use the ss
tool for the most complete information about a Unix Domain Socket.
To examine a socket on the filesystem, the stat
utility shows the most relevant information. Run it on the sockets that you created earlier:
- stat /tmp/stream.sock /tmp/datagram.sock
You will receive output like the following:
Output File: /tmp/stream.sock
Size: 0 Blocks: 1 IO Block: 131072 socket
Device: 48h/72d Inode: 1742 Links: 1
Access: (0755/srwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2021-03-01 18:10:25.025755168 +0000
Modify: 2021-03-01 18:10:25.025755168 +0000
Change: 2021-03-01 18:22:42.678231700 +0000
Birth: -
File: /tmp/datagram.sock
Size: 0 Blocks: 1 IO Block: 131072 socket
Device: 48h/72d Inode: 1743 Links: 1
Access: (0755/srwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2021-03-01 18:10:25.025755168 +0000
Modify: 2021-03-01 18:10:25.025755168 +0000
Change: 2021-03-01 18:10:25.025755168 +0000
Birth: -
Notice that for each file, the type is socket
(highlighted at the far right of the output) and the access mode has an s
character preceding the file’s permissions.
The ls
utility will also indicate if a file is a socket. Run ls -l
to examine the files:
- ls -l /tmp/stream.sock /tmp/datagram.sock
You will receive output like the following. Again note that for sockets, the file mode includes the s
character before the file permission fields:
Outputsrwxr-xr-x 1 root root 0 Mar 1 18:10 /tmp/datagram.sock
srwxr-xr-x 1 root root 0 Mar 1 18:10 /tmp/stream.sock
Now that you have created Unix Domain Sockets, and learned how to examine them using the ss
and various filesystem based tools, the next step is to test the sockets using a tool like netcat.
The netcat utility can be used to connect to Unix Domain Sockets, as well as TCP and UDP sockets that you already learned about earlier in this tutorial. To connect to the example sockets that you created, you will need to specify an extra -U
flag when running the netcat command. This flag tells netcat to connect to a UDS, as opposed to a TCP or UDP based network socket.
Additionally, if the socket is datagram-based, you will use the -u
flag to instruct netcat to use datagrams as we learned in the Datagram Socket section of this tutorial.
Let’s start examining UDS sockets by connecting to the stream-based socket with the following command:
- nc -U -z /tmp/stream.sock
The -U
tells netcat that it is connecting to a Unix Domain Socket.
The -z
option ensures that netcat only connects to a socket, without sending any data.
The /tmp/stream.sock
is the address of the socket on the filesystem.
You will not receive any output from netcat when you run the command. However, if a socket is not available, netcat will output an error message like the following:
Outputnc: unix connect failed: No such file or directory
nc: /tmp/stream.sock: No such file or directory
So the absence of output from netcat when testing a stream-based UDS socket means that the connection was successful.
Repeat the testing process, this time for the datagram-based UDS:
- nc -uU -z /tmp/datagram.sock
The additional -u
flag is added to tell netcat that the remote socket is a datagram socket. Again, you will not receive any output if the test is successful.
If there is no socket at the address, you will receive an error like the following:
Outputnc: unix connect failed: No such file or directory
nc: /tmp/datagram.sock: No such file or directory
To clean up your sockets, you’ll need to run the fg
(foreground) command for each socat process that you created. Then you’ll use CTRL+C
to close each socat.
Run fg
to bring the datagram-based socat
instance to the foreground of your terminal:
- fg
You will receive output like the following:
Outputsocat unix-recvfrom:/tmp/datagram.sock,fork /dev/null
Run CTRL+C
to close it. You will not receive any output.
Now run fg
again to clean up the first stream-based UDS socket.
Again you should have output like the following:
Outputsocat unix-listen:/tmp/stream.sock,fork /dev/null
Run CTRL+C
to end the process. You will not receive any output.
You have now created, examined, and tested Unix Datagram Sockets sockets on your system. Try experimenting with netcat and socat
to become more familiar with how you can send and receive data over a UDS, as well as how you can test and troubleshoot Unix Domain sockets.
In this tutorial you explored how different kinds of sockets are used on a Linux system. You learned about stream-based sockets, which typically use TCP for network communication. You also learned about datagram-based sockets, which use UDP to send data over networks. Finally, you explored how Unix Domain Sockets can be either stream or datagram-based on a local server.
In each section you used the ss
utility to gather information about sockets on a Linux system. You learned how the different flags that the ss
tool provides can help you limit its output to specific types of sockets when you are examining sockets on a system.
Finally, you used the netcat and socat
tools to create and connect to each of the three different types of sockets discussed in this tutorial. The netcat utility is widely used to connect to sockets, but it can also create sockets. Its documentation (man nc
) contains many examples of how it can be used in either mode. The socat
utility is a more advanced tool that can be used to connect to and many different types of sockets that are not covered in this tutorial. Its documentation (man socat
) also contains numerous examples of the different ways that it can be used.
Understanding what sockets are and how they work is a core system administration skill. The tools and techniques that you experimented with in this tutorial will help you become more familiar with sockets, and how to troubleshoot them if your servers and applications are not communicating with each other correctly.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
This is super helpful
Digital Ocean is one of the best educational organizations in the world~!
Haha~! Just kidding~! I’m a paid customer!
This tutorial is super GREAT!
Useful and practical tutorial of sockets
nicely written. Great tutorial. I love the hands on approach!
I like this tutorial, but I simplest example “how to send data to socket using Linux tools” and “how to read data in socket using Linux tools” would be great for complete package of this tutorial
This comment has been deleted
This comment has been deleted
This comment has been deleted
Good tutorial. Thank you
This comment has been deleted