Sockets | UNIX Domain Socket (IPC) | Network Socket

Enable inter-process communication (IPC) 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. A network socket is effectively a network port (location) as seen from inside the target node (machine).

The server listens (passive socket); the client connects (active socket).

Socket Types

Utilities

Use socat(1)

# Usage syntax
socat [options] <address> <address>
# <address>
protocol:ip:port

TCP-based Stream Sockets

Stream sockets are connection oriented; 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.

Creating TCP-based Stream Sockets

Emulate a web server listening for HTTP requests on port 8080 (the alternative HTTP port); 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 &

Examining TCP-based Stream Sockets

Show socket statistics

ss -tln
State          Recv-Q         Send-Q     Local Address:Port    Peer Address:Port   Process
LISTEN         0              5          0.0.0.0:8080          0.0.0.0:*
LISTEN         0              5           [::]:8080             [::]:*
...

Connecting to TCP-Based Stream Sockets

Connect to the IPv4 socket, created to listen on all interfaces, over the local loopback address.

nc -4 -vz 127.0.0.1 8080
Connection to 127.0.0.1 8080 port [tcp/http-alt] succeeded!

Similarly for IPv6 connection

nc -6 -vz ::1 8080

Cleanup : Disconnect/Delete Sockets

Bring each background socket process (job) to the foreground and kill it; first display all by number (jobs), then bring each to foreground (fg %$n), killing each in turn (CTRL-C) .

/mnt/shared # jobs
[2]+  Running                    socat TCP6-LISTEN:8080,ipv6only=1,fork /dev/null
[1]-  Running                    socat TCP4-LISTEN:8080,fork /dev/null
/mnt/shared # fg %2
socat TCP6-LISTEN:8080,ipv6only=1,fork /dev/null    # CTRL-C
/mnt/shared # fg %1
socat TCP4-LISTEN:8080,fork /dev/null               # CTRL-C
/mnt/shared # jobs
/mnt/shared #

Datagram 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: The protocol (TCP/UDP) is not included in the human-readable version of the socket address, but 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.

Creating Datagram Sockets

Emulate an NTP server listening for requests on UDP port 123 using sockets. Then examine them using the ss and nc commands.

First create two UDP sockets that are listening for connections on port 123, using IPv4 and IPv6 interfaces:

socat UDP4-LISTEN:123,fork /dev/null &
socat UDP6-LISTEN:123,ipv6only=1,fork /dev/null &

Examining Datagram Sockets

Show socket statistics

ss -uln |grep 123
UNCONN 0      0            0.0.0.0:123        0.0.0.0:*
UNCONN 0      0               [::]:123           [::]:*

Testing Datagram Sockets

Connect

nc -4 -u -vz 127.0.0.1 123
Connection to 127.0.0.1 123 port [udp/ntp] succeeded!

Cleanup using same method as with TCP Sockets

Unix Domain Socket | Wikipedia

About

A Unix domain socket aka UDS or IPC socket (inter-process communication socket) is a data communications endpoint for exchanging data between processes executing on the same host operating system; UDS data is exchanged between programs directly in the OS kernel via files on the host filesystem; programs read and write to their shared socket file, bypassing network based sockets and protocols entirely. It is also referred to by its address family AF_UNIX. UDS may be stream-based or datagram-based. Valid socket types in the UNIX domain are:

The Unix domain socket facility is a standard component of POSIX operating systems.

The API for Unix domain sockets is similar to that of an Internet socket, but rather than using an underlying network protocol, all communication occurs entirely within the operating system kernel.

UDS is used widely by database systems that do not need to be connected to a network interface; 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.

Creating Unix Domain Sockets

Create both stream-based and datagram-based Unix Domain Sockets without using TCP or UDP to encapsulate data to send over networks.

# Create stream-based UDS
socat UNIX-LISTEN:/tmp/stream.sock,fork /dev/null &
# Create datagram-based UDS
socat UNIX-RECVFROM:/tmp/datagram.sock,fork /dev/null &

Examining Unix Domain Sockets

ss -xln 
Netid         State       Recv-Q    Send-Q   Local Address:Port          Peer Address:Port   Process
u_str         LISTEN      0         5        /tmp/stream.sock 269122     * 0
u_dgr         UNCONN      0         0        /tmp/datagram.sock 269288   * 0
...

Since UDSs 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.

@ ls

/mnt/shared # ls /tmp
...
srwxr-xr-x    1 root     root           0 Dec  8 14:34 datagram.sock
srwxr-xr-x    1 root     root           0 Dec  8 14:33 stream.sock

@ stat

/mnt/shared # stat /tmp/stream.sock /tmp/datagram.sock
  File: /tmp/stream.sock
  Size: 0               Blocks: 0          IO Block: 4096   socket
Device: 9eh/158d        Inode: 1366937     Links: 1
Access: (0755/srwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2022-12-08 14:33:03.611342000 -0500
Modify: 2022-12-08 14:33:03.611342000 -0500
Change: 2022-12-08 14:33:03.611342000 -0500
  File: /tmp/datagram.sock
  Size: 0               Blocks: 0          IO Block: 4096   socket
Device: 9eh/158d        Inode: 1366942     Links: 1
Access: (0755/srwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2022-12-08 14:34:06.231657000 -0500
Modify: 2022-12-08 14:34:06.231657000 -0500
Change: 2022-12-08 14:34:06.231657000 -0500

Connecting to Unix Domain Sockets

# Connect to stream-based UDS
nc -U -z /tmp/stream.sock
# Connect to datagram-based UDS
nc -uU -z /tmp/datagram.sock

Cleanup using same method as with TCP Sockets

File Descriptors

In Unix and Unix-like computer operating systems, a file descriptor (FD, less frequently fildes) is a process-unique identifier (handle) for a file or other input/output resource, such as a pipe or network socket.

File descriptors typically have non-negative integer values, with negative values being reserved to indicate "no value" or error conditions.

File descriptors are a part of the POSIX API. Each Unix process (except perhaps daemons) should have three standard POSIX file descriptors, corresponding to the three standard streams:

# Name symbolic constant <unistd.h> file stream <stdio.h>
0 Standard input STDIN_FILENO stdin
1 Standard output STDOUT_FILENO stdout
2 Standard error STDERR_FILENO stderr

File Descriptor 3

# Needn't exist
☩ ls /dev/tcp                                                             
ls: cannot access '/dev/tcp': No such file or directory                   

# Create
☩ exec 3<>/dev/tcp/google.com/80                                          

# Not seen as either a file or directory
☩ ls /dev/tcp                                                             
ls: cannot access '/dev/tcp': No such file or directory                   

# Send GET request
☩ echo -e "GET / HTTP/1.1\n\r" >&3                                        

# Read response
☩ cat <&3                                                                 
HTTP/1.1 200 OK                                                           
...                                      
Content-Type: text/html; charset=ISO-8859-1                               
...                                                                                              
Transfer-Encoding: chunked  

539e                                                                      
<!doctype html><html ...