- Что такое сокеты Unix и как они работают?
- Что такое сокеты?
- Как работают сокеты?
- Использование сокетов на практике
- How Linux Uses Sockets
- What are Linux Sockets?
- What are Linux Sockets Used for
- Types of Linux Sockets
- Stream-Oriented Sockets
- Datagram-Oriented Sockets
- Raw Sockets
- Sequenced Sockets
- How Sockets Work in Linux
Что такое сокеты Unix и как они работают?
Сокеты Unix — это форма связи между двумя процессами, которая отображается в виде файла на диске. Этот файл может использоваться другими программами для установления очень быстрых соединений между двумя или более процессами без каких-либо сетевых накладных расходов.
Что такое сокеты?
Сокеты — это прямая связь между двумя процессами. Представьте, что вы хотите позвонить своему другу по дороге; вы можете сделать звонок, направив его через вашу телефонную компанию и обратно в их дом, или вы можете провести провод прямо в их дом и исключить посредника. Последнее, очевидно, непрактично в реальной жизни, но в мире Unix очень распространено устанавливать эти прямые связи между программами.
Собственное имя для сокетов unix — сокеты домена Unix (Unix Domain Sockets), потому что все они находятся на одном компьютере. В некотором смысле сокеты — это сеть, полностью содержащаяся в ядре; вместо того, чтобы использовать сетевые интерфейсы и соответствующие накладные расходы для отправки данных, те же самые данные могут быть отправлены напрямую между программами.
Несмотря на создание файлов на диске, сокеты Unix на самом деле не записывают данные, которые они отправляют на диск, так как это было бы слишком медленно. Вместо этого все данные хранятся в памяти ядра; единственная цель файла сокета — поддерживать ссылку на сокет и давать ему разрешения файловой системы для управления доступом.
В современных системах файлы управления сокетами обычно расположены в директории /run/. Например, файл управления сокетом MariaDB обычно находится по адресу /run/mysqld/mysqld.sock, а файл службы Tor по пути /run/tor/socks. Этот файл ничего не содержит, и вы не должны изменять его напрямую, за исключением разрешений, где это применимо. Это просто имя.
А файлы управления сокетами обычно расположены в директории /usr/lib/systemd/system/. Например, файл управления сокетом MariaDB обычно находится по адресу:
/usr/lib/systemd/system/mariadb.socket
Это простой текстовый файл с настройками, например:
[Unit] Description=MariaDB 10.6.5 database server (socket activation) Documentation=man:mariadbd(8) Documentation=https://mariadb.com/kb/en/library/systemd/ [Socket] ############################################################################## ## USERs can override ## ## ## by creating a file in /etc/systemd/system/mariadb.socket.d/MY_SPECIAL.conf ## and adding/setting the following under [Socket] will override this file's ## settings. SocketUser=mysql SocketMode=777 ListenStream=@mariadb ListenStream=/run/mysqld/mysqld.sock ListenStream=3306 # Backlog=150
Обратите внимание на директивы ListenStream (путь до файла сокета), вторая ListenStream (номер порта), SocketUser (владелец файла сокета), SocketMode (режим, права доступа к сокету).
Как работают сокеты?
Сокеты просто предоставляют фактическое оборудование для перемещения данных. Сокеты на основе TCP называются потоковыми сокетами, куда все данные будут поступать по порядку. Сокеты на основе UDP — это сокеты для дейтаграмм, для которых порядок (или даже доставка) не гарантируется. Существуют также необработанные (raw) сокеты, которые не имеют каких-либо ограничений и используются для реализации различных протоколов и утилит, которые должны проверять низкоуровневый сетевой трафик, например Wireshark.
Сокеты обычно по-прежнему используют TCP или UDP, поскольку они не являются чем-то особенным, кроме причудливого канала внутри ядра. TCP и UDP — это транспортные протоколы, которые определяют, как данные передаются с места на место, но не заботятся о том, что это за данные. TCP и UDP обеспечивают платформу для большинства других протоколов, таких как FTP, SMTP и RDP, которые работают на более высоких уровнях.
Приложение может использовать несколько иную реализацию TCP; потоковые сокеты используют протокол SOCK_STREAM, который TCP также использует для транспорта почти всё время, и хотя они в основном взаимозаменяемы, технически они немного отличаются. Хотя это низкоуровневый материал и на самом деле это не то, о чем вам придётся беспокоиться, просто знайте, что большая часть трафика, отправляемого через сокеты домена UNIX, основана на TCP или UDP или, по крайней мере, очень похожа на трафик этих транспортных протоколов, и TCP отправляется через сокеты домена UNIX быстрее, чем TCP через сетевые интерфейсы, такие как порты.
Использование сокетов на практике
Сокеты Unix обычно используются в качестве альтернативы сетевым TCP-соединениям, когда процессы выполняются на одном компьютере. Данные обычно по-прежнему отправляются по тем же протоколам; но поскольку они просто остаются на той же машине, в том же домене (отсюда и название сокеты домена UNIX), поэтому им никогда не нужно беспокоить петлевой (loopback) сетевой интерфейс для подключения к самому себе.
Самым ярким примером этого является Redis, чрезвычайно быстрое хранилище значений ключей, которое полностью работает в памяти. Redis часто используется на том же сервере, который обращается к нему, поэтому обычно можно использовать сокеты. На таких низких уровнях и с учётом того, насколько быстр Redis, сокеты обеспечивают повышение производительности на 25% в некоторых синтетических тестах.
Если вы подключаетесь к базе данных MySQL, вы также можете использовать сокет. Обычно вы подключаетесь к ХОСТ:ПОРТ из удалённой системы, но если вы подключаетесь к базе данных на том же сервере (например, REST API обращается к базе данных), вы можете использовать сокеты для ускорения. При обычном использовании сокеты не дадут ощутимого прироста производительности, но при высокой нагрузке это иначе: более 20% прироста производительности на 24 ядрах высокого класса со 128 одновременными пользователями и миллионом запросов в секунду. Увидите ли вы выгоду от сокетов при описанных условиях? Да, но при такой нагрузке всё равно придётся заняться репликацией и балансировкой нагрузки.
Если вы хотите работать с сокетами вручную, вы можете использовать утилиту socat, чтобы открыть их через сетевые порты:
socat TCP-LISTEN:12345 UNIX-CONNECT:/var/lib/socket.sock
Это технически противоречит назначению сокетов домена Unix, но может использоваться для отладки на транспортном уровне.
How Linux Uses Sockets
Linux provides a flexible platform for communication between a wide range of applications and devices. Its robust networking component makes Linux a popular solution for running web servers and developing distributed systems and applications.
The Linux networking stack includes many network interfaces, protocols, and other components. Linux sockets are an important network data-transfer mechanism used to build networked applications, implement protocols and provide network services.
This article will focus on what Linux sockets are, the types of sockets, and how they work.
What are Linux Sockets?
Sockets are Linux file descriptors that serve as the communication end-points for processes running on that device. Each Linux socket consists of the device’s IP address and a selected port number.
A socket connection is a bidirectional communication pipe that allows two processes to exchange information within a network.
What are Linux Sockets Used for
The typical sockets use case is the client-server network interaction model. In this model, the server process socket listens and waits for clients’ requests. The clients exchange information with the server using TCP/IP, UDP/IP network protocols, and application-level protocols such as IMAP, POP3, SMTP, or FTP.
Although sockets primarily connect processes on a computer network, they also enable communication between processes on the same device. The same-machine connections use the IPC (Inter-process communication) sockets, also known as Unix domain sockets.
The IPC sockets are helpful because they eliminate the need for loopback network interfaces when applications such as Redis or MySQL use REST API to communicate with the database on the same machine.
Types of Linux Sockets
There are four main types of Linux sockets.
- Stream-oriented sockets provide a reliable, connection-based communication channel.
- Datagram-oriented sockets offer a connectionless UDP-based channel.
- Raw sockets allow direct access to the underlying networking protocols.
- Sequenced packet sockets guarantee that the sent packets will arrive in the original order.
The sections below provide details on each socket type.
Stream-Oriented Sockets
Stream-oriented sockets are mainly used in TCP/IP communication. Since TCP is a connection-oriented protocol, the stream sockets establish a persistent connection between two communicating processes.
The data packets sent over stream sockets arrive reliably and in the correct order, making this socket type suitable for web and email servers.
You can list the currently listening TCP sockets on Linux with the ss command:
Datagram-Oriented Sockets
Datagram-oriented sockets support the connectionless UDP (User Datagram Protocol). Unlike stream sockets, datagram sockets do not establish a permanent connection between two interacting processes. Instead, each packet is an independent datagram, a self-contained message whose arrival or integrity is not guaranteed.
Applications usually employ datagram-oriented UDP sockets when they require low overhead or real-time communication. For example, online gaming and VoIP use UDP because they prioritize the speed of information exchange over the integrity of the information.
The following ss command shows the active datagram-oriented UDP sockets on a Linux system:
Note: Bare Metal Cloud servers allow you to deploy server instances with cloud agility and connection stability, while avoiding the hypervisor overhead.
Raw Sockets
Raw sockets allow processes to access the underlying communication protocols directly. This property enables processes to avoid transport-layer formatting associated with a protocol and exchange the data at the lowest level.
Network applications that need a high level of control over communication, such as ping and traceroute, require raw sockets to function correctly. However, since raw sockets provide easy access to the link layer, their extensive use can be a security concern.
Sequenced Sockets
Sequenced sockets allow processes to manage incoming packets at the network layer before the packets move to the transport layer. They offer a middle-ground solution between stream and datagram-oriented sockets.
- Like stream-oriented sockets, sequenced sockets are connection-oriented.
- On the other hand, they offer datagram-like delineated packet boundaries.
How Sockets Work in Linux
Each Linux socket uses a specific domain and type. The domain determines the protocol family the socket will use, such as IPv4 or IPv6. The socket type specifies whether the socket will support reliable two-way communication (e.g., TCP) or one-way communication with best-effort delivery (e.g., UDP).
Sockets perform all the communication functions through the socket API. Using API calls, users can:
- Establish and manage connections with other systems.
- Obtain information about relevant network resources.
- Transfer data to and from the machine.
- Perform system functions.
- Stop the socket connections.
For example, to use a stream-oriented TCP socket in Linux, a user needs to start by specifying the type with the socket() system call. The next API calls differ depending on the system’s role in the network.
On the server side:
- bind() — Binds a socket to a network address and port.
- listen() — Tells the server to wait for incoming connections to the specified network location.
- accept() — Receives the client connections.
- read() and write() — Communicate with the remote endpoint once the server establishes the communication and creates a new socket for the client.
On the client side:
- connect() — Connects with the server process. Takes the address of the remote server socket as an argument.
- send() and recv() — Send and receive data, respectively.
- close() — Ends the connection between the client and the server.
Datagram communication, on the other hand, does not require establishing a connection. Therefore, the server and the clients use the same system calls to exchange information between the sockets.
The socket() call initializes the socket. However, since there is no need to establish a permanent connection, the datagram socket does not utilize the bind() , listen() , and accept() calls like the stream-oriented type. Instead, the send() and recv() calls conduct packet exchange directly.
After reading this article, you should understand the concept of a Linux socket. The article explained how Linux sockets work and discussed the most common types.