Как создать sock файл

Обновлено: 06.07.2024

Во первых этот материал для тех, кто уже пробовал программировать сокеты, а во вторых здесь будет говорится только о сокетах INET (то есть IPv4) STREAM (т.е. TCP), так как они составляют не менее 99% используемых сокетов. От сокета STREAM можно получить лучшую производительность, чем от какого-то другого. Так же приоткроем тайну того, что такое сокет и дадим несколько советов, как работать с блокирующими и неблокирующими сокетами. Начнем разбираться с блокирующих сокетов, т.к. необходимо знать, как они работают, прежде чем работать с неблокирующими сокетами,

Содержание.

Проблема с пониманием работы сокетов заключается в том, что сокет может означать несколько разных тонких вещей в зависимости от контекста. Итак, сначала проведем различие между клиентским сокетом - конечной точкой диалога и серверным сокетом, который больше похож на оператора коммутатора. Клиентское приложение, например браузер, использует исключительно клиентские сокеты, а веб-сервер, с которым он разговаривает, использует как серверные, так и клиентские сокеты.

Что такое сокет и как он создается?

Грубо говоря, когда происходит переход по ссылке на сайте, браузер делает что-то вроде следующего:

Когда устанавливается соединение sock.connect() , то сокет sock можно использовать для отправки текста страницы. Тот же сокет прочитает ответ, а затем будет уничтожен. Клиентские сокеты обычно используются только для разового обмена данными или небольшого набора последовательных обменов данными.

То, что происходит на веб-сервере, немного сложнее. Сначала веб-сервер создает серверный сокет:

Наконец, аргумент 5 вызова serv_sock.listen(5) , говорит модулю socket , чтобы сервер поставил в очередь до 5 клиентов на подключение (нормальный максимум), прежде чем отклонять остальные запросы. Если остальная часть кода написана правильно, то этого должно быть достаточно.

Теперь, когда есть серверный сокет, прослушивающий 443 порт, можно войти в основной цикл веб-сервера:

Существует 3 основных способа, которыми этот цикл может работать:

  • диспетчеризация потока для работы с клиентским сокетом,
  • создание нового процесса для работы с клиентским сокетом,
  • реструктуризация всего приложения для использования неблокирующих сокетов и мультиплексирование между серверным сокетом и любыми активными клиентскими сокетами используя модуль select .

Подробнее об этом позже. Сейчас важно понять, что это все, что делает серверный сокет. Он не отправляет и не получает никаких данных. Он просто воспроизводит/создает клиентские сокеты. Каждый клиентский сокет создается в ответ на то, что какой-то новый клиентский сокет выполняет подключение sock.connect() к серверу на определенный хост и порт. На этот запрос, сервер создает новый клиентский сокет, и как только он это сделает то сразу возвращается к прослушиванию следующих подключений. Два клиента могут свободно общаться, например на каком-нибудь динамически выделенном порту, который будет закрыт после общения.

Межпроцессорное взаимодействие (IPC).

Если необходим быстрый IPC между двумя процессами на одной машине, то следует изучить каналы Pipe() или общую память (объекты Value() и Array() ). Если все же решите использовать socket.AF_INET сокеты, то необходимо привязать серверный сокет к localhost . На большинстве платформ это позволит сократить несколько уровней сетевого кода и будет работать немного быстрее.

Смотрите также модуль multiprocessing , который интегрирует межплатформенный IPC в API более высокого уровня.

Использование сокета.

Первое, на что следует обратить внимание, это то, что клиентский сокет браузера и клиентский сокет веб-сервера - полностью идентичны. То есть, это диалог одноранговый. Обычно сокет, который подключается к серверу начинает диалог, отправляя запрос или возможно, вход в систему. Но это уже решение программиста, а не сокета, как построить диалог.

Для приема/передачи данных можно использовать методы объекта сокета Socket.send() и Socket.recv() , а можно превратить клиентский сокет в файловый объект и использовать чтение/запись. По поводу использования сокета, как файлового объекта, необходимо сделать предупреждение, что в сокетах, при выполнении записи, нужно использовать вызов file.flush() . Сокеты имеют дело с буферизованными "файлами" и распространенной ошибкой является - записать что-то и не вызвать file.flush() , а затем перейти в режим чтения ответа. При этом можно бесконечно долго ждать ответа, т. к. записанные данные все еще могут оставаться в выходном буфере.

Но если в планах повторно использовать открытый сокет для каких-то задач, то нужно понимать, что в сокетах нет EOT - "end of trensfer" (конец файла). ЕЩЕ РАЗ: если сокет после вызова методов Socket.send() или Socket.recv() возвращает 0 байтов, то соединение было разорвано. Если соединение не было разорвано, то можно вечно ждать получения данных вызовом Socket.recv() , т. к. сокет не может сказать, что читать больше нечего.

В интересах создания первого приложения с использованием сокетов, вышесказанные улучшения оставлены как упражнение для читателя.

Прием/передача двоичных данных.

Вполне возможно отправлять двоичные данные через сокет. Основная проблема заключается в том, что не все машины используют одни и те же форматы для двоичных данных. Например, чип Motorola будет представлять 16-битное целое число, например 1 в виде двух шестнадцатеричных байтов - 00 01. Intel и DEC переворачивают байты - то же самое число 1 здесь будет выглядеть как 01 00. Модуль socket имеет функции для преобразования 16 и 32-битных целых чисел - socket.ntohl() , socket.htonl() , socket.ntohs() и socket.htons() , где в названиях первая буква означает n - сеть, а h - хост, а последняя s - короткий, а l - длинный. Там, где сетевой порядок является порядком хоста, функции ничего делать не будут, но там, где машина перевернула байты, они соответствующим образом все поменяют.

Закрытие соединения сокета.

Строго говоря, сначала необходимо использовать вызов объекта сокета shutdown() , прежде чем закрыть его командой Socket.close() . Вызов Socket.shutdown() - это предупреждение для сокета на другом конце. В зависимости от аргумента, который передавать, это может означать "Я больше не буду отправлять, но я все равно буду слушать" или "Я не слушаю, мне по барабану". Разработчики библиотек сокетов настолько привыкли к тому, что программисты пренебрегают этим элементом этикета, что у некоторых, обычный вызов Socket.close() - означает последовательность вызовов: Socket.shutdown() ; Socket.close() . Поэтому в большинстве ситуаций явный вызов Socket.shutdown() не требуется.

Python делает еще один шаг к автоматическому завершению соединения, это постоянный мониторинг открытых сокетов сборщиком мусора. Сборщик мусора автоматически закрывает соединение, если это необходимо. Но полагаться на это - очень плохая привычка. Если сокет просто исчезнет без закрытия, то сокет на другом конце может зависнуть бесконечно думая, что сервер просто медленно работает и когда закончит, то закроет сокет.

Когда умирают сокеты.

Худшее в использовании блокирующих сокетов - это то, что происходит, когда одна из сторон соединения резко падает (без закрытия). Сокет скорее всего зависнет. TCP - надежный протокол и он будет долго ждать, прежде чем отказаться от соединения. Если использовать потоки, то весь поток практически умрет. С этим ничего не поделаешь и если не делать глупостей, таких как держать блокировку при выполнении чтения, то поток не съест много ресурсов.

Не пытайтесь убить поток - одна из причин того, что потоки более эффективны, чем процессы, заключается в том, что у них нет накладных расходов, связанных с автоматическим повторным использованием ресурсов. Другими словами, если удастся убить поток, то вся программа, скорее всего, упадет.

Неблокирующие сокеты

Чтобы сделать сокет неблокирующим, в Python используют вызов Socket.setblocking(False) . Вызов делается после создания сокета, но перед его использованием. Если программист не очень умный, то скорее всего попытается переключаться туда и обратно (с блокирующего сокета на неблокирующий).

Основное механическое отличие состоит в том, что вызовы Socket.send() , Socket.recv() , Socket.connect() и Socket.accept() могут возвращать результат без каких-либо действий. И здесь есть несколько вариантов. Можно проверить ответ, который вернул соответствующий вызов и код ошибки и вообще свести себя с ума. Если не верите, попробуйте как-нибудь. Приложение будет разрастаться, глючить и загружать процессор. Так что давайте пропустим безумные решения и сделаем все правильно.

Одним из возможных решений является делегирование работы с клиентами отдельным потокам. Однако создание потоков и переключение контекстов между ними на самом деле не является дешевой операцией. Для решения этой проблемы существует так называемый асинхронный способ работы с сокетами. Основная идея состоит в том, чтобы делегировать поддержание состояния сокета операционной системе и позволить ей уведомлять программу, когда есть что-то для чтения из сокета или когда он готов к записи. Для этого можно использовать вызов операционной системы select , подробнее о нем можно посмотреть командой терминала Unix $ man select

В Python такой вызов сделать совсем несложно, для этой цели используйте встроенный модуль select , в частности вызов select.select() :

Здесь передается в select.select() три списка:

  • potential_readers содержит все сокеты, которые нужно прочитать,
  • potential_writers содержит все сокеты, в которые надо что-то записать,
  • potential_errs - которые нужно проверять на наличие ошибок (обычно оставляют пустым).

Следует отметить, что один сокет может входить в разные списки. Вызов select.select() блокируется, но можно задать ему таймаут. Как правило, это разумный поступок - дайте ему длительный таймаут (скажем, минуту), если нет веских причин поступить иначе.

Взамен получаем три списка. Они содержат сокеты, которые действительно доступны для чтения, записи и содержат ошибки. Каждый из этих списков является подмножеством, возможно пустым, соответствующего переданного списка в select.select() .

Если есть "серверный" сокет, то поместим его в список potential_readers . Если он появится в списке ready_to_read , то вызов .accept почти наверняка сработает. Если сервер создал новый сокет для подключения, то поместим его в список potential_writers . Если он отображается в списке ready_to_write , то есть неплохие шансы, что он подключился.

Предупреждение о переносимости: в Unix, модуль select работает как с сокетами, так и с файлами. Не пытайтесь использовать это в Windows. В Windows, модуль select работает только с сокетами. Также обратите внимание, что в языке C многие из более продвинутых параметров сокетов в Windows выполняются иначе. Фактически, в Windows обычно используют потоки, которые работают очень и очень хорошо с сокетами.

Пример асинхронного сервера с вызовом select.select() .

В примере вызывается select.select() , для опроса сокетов операционной системой, готовы ли они к записи, чтению или есть ли какое-то ошибки в сокетах. Этот вызов блокирует программу (если не передан аргумент тайм-аута) до тех пор, пока не будут готовы какие нибудь из переданных сокетов. По готовности хоты-бы одного из сокетов, вызов select.select() вернет три списка с сокетами для указанных операций. Затем программа последовательно перебирает эти списки и выполняет соответствующие операции.

Так работают сокеты на низком уровне. В большинстве случаев нет необходимости реализовывать логику на таком низком уровне. Рекомендуется использовать некоторые абстракции более высокого уровня, такие как | Twisted |, | Tornado | или | ZeroMQ |, в зависимости от ситуации.

Кто-нибудь знает, почему мой /var/run/mysqld/mysqld.sock файл сокета не будет на моем компьютере при установке (или переустановке) MySQL 5.1?

Прямо сейчас, когда я пытаюсь запустить сервер с mysqld, я получаю похожие ошибки Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) when trying to connect , но создание пустого файла с таким именем (как это предлагалось на форумах по Ubuntu) было неудачным.

У меня были и mysql, и postgres, которые хорошо работали, пока я не перешел на natty некоторое время назад; Я часами гулял по обеим базам данных, пытаясь выяснить, что происходит. Я могу отказаться от postgres, но я не могу работать без рабочей копии mysql.

Самая странная часть: я использую Kubuntu, и я понимаю, что KDE использует mysql для хранения пользовательских разрешений и т. Д. У меня не возникает никаких странных проблем с разрешениями; Могу ли я считать, что это означает (как-то?) MySQL на самом деле работает?

Может быть, эти файлы сокетов живут в другом месте в natty? Будет ли проще просто переустановить ОС fresh? На данный момент я открыт для любых предложений, которые перестанут тратить мое время.

Вам необходимо сначала запустить сервер MySQL, а затем этот файл /var/run/mysqld/mysqld.sock будет создан. Как сказал @Paul, вы должны удалить любой файл, который вы поместили в это место.

Файл сокета на самом деле не содержит данных, он переносит их. Это особый, необычный тип файла, созданный с помощью специальных системных вызовов / команд. Это не обычный файл.

Это похоже на канал, который сервер и клиенты могут использовать для подключения и обмена запросами и данными. Кроме того, он используется только локально. Его значение заключается просто в согласованном месте встречи в файловой системе.

Создание простого старого файла и размещение его в этом месте может фактически помешать серверу, создающему его . и тем самым помешать локальным клиентам подключиться к серверу.

Я рекомендую удалить любой файл, который вы положили в папку. Специальный файл сокета создается сервером.

Спасибо за объяснение файлов сокетов, и извините за плохо сформулированный вопрос: моя первоначальная проблема заключалась в том, что файл сокетов отсутствовал - ошибка, которую продолжал Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) when trying to connect но как это создано? потому что у меня все еще нет этого . -Есть идеи? Возможно, у вас есть клиент mysql, который ожидает, что сокет находится в этом месте, но сервер не создает его там (или сервер не работает). Если сервер работает, посмотрите в / tmp или используйте find или locate для найдите файл сокета, затем запустите клиент mysql с -S <путь к файлу сокета>

Когда вы укажете host=localhost , клиент MySQL попытается войти на сервер MySQL, используя именованный канал Unix, для которого требуется .sock файл.

Это можно обойти, указав host = 127.0.0.1. Это заставит клиента mysql использовать TCP для подключения к серверу.

В данной статье будет рассмотрено понятие сокета в операционной системе Linux: основные структуры данных, как они работают и можно ли управлять состоянием сокета с помощью приложения. В качестве практики будут рассмотрены инструменты netcat и socat.

Что такое сокет?

Сокет - это абстракция сетевого взаимодействия в операционной системе Linux. Каждому сокету соответствует пара IP-адрес + номер порта. Это стандартное определение, к которому привыкли все, спасибо вики. Хотя нет, вот здесь лучше описано. Поскольку сокет является только лишь абстракцией, то связка IP-адрес + номер порта - это уже имплементация в ОС. Верное название этой имплементации - "Интернет сокет". Абстракция используется для того, чтобы операционная система могла работать с любым типом канала передачи данных. Именно поэтому в ОС Linux Интернет сокет - это дескриптор, с которым система работает как с файлом. Типов сокетов, конечно же, намного больше. В ядре ОС Linux сокеты представлены тремя основными структурами:

struct socket - представление сокета BSD, того вида сокета, который стал основой для современных "Интернет сокетов";

struct sock - собственная оболочка, которая в Linux называется "INET socket";

struct sk_buff - "хранилище" данных, которые передает или получает сокет;

Как видно по исходным кодам, все структуры достаточно объемны. Работа с ними возможна при использовании языка программирования или специальных оберток и написания приложения. Для эффективного управления этими структурами нужно знать, какие типы операций над сокетами существуют и когда их применять. Для сокетов существует набор стандартных действий:

socket - создание сокета;

bind - действие используется на стороне сервера. В стандартных терминах - это открытие порта на прослушивание, используя указанный интерфейс;

listen - используется для перевода сокета в прослушивающее состояние. Применяется к серверному сокету;

connect - используется для инициализации соединения;

accept - используется сервером, создает новое соединение для клиента;

send/recv - используется для работы с отправкой/приемом данных;

close - разрыв соединения, уничтожение сокета.

Если о структурах, которые описаны выше, заботится ядро операционной системы, то в случае команд по управлению соединением ответственность берет на себя приложение, которое хочет пересылать данные по сети. Попробуем использовать знания о сокетах для работы с приложениями netcat и socat.

netcat

Оригинальная утилита появилась 25 лет назад, больше не поддерживается. На cегодняшний день существуют порты, которые поддерживаются различными дистрибутивами: Debian, Ubuntu, FreeBSD, MacOS. В операционной системе утилиту можно вызвать с помощью команды nc, nc.traditional или ncat в зависимости от ОС. Утилита позволяет "из коробки" работать с сокетами, которые используют в качестве транспорта TCP и UDP протоколы. Примеры сценариев использования, которые, по мнению автора, наиболее интересны:

перенаправление входящих/исходящих запросов;

трансляция данных на экран в шестнадцатеричном формате.


Введем команду на открытие порта на машине Destination: nc -ulvvp 7878

Запускаем соединение из машины Source: nc 10.0.2.4 4545

В итоге получаем возможность читать данные от машины Source:


В машине Destination:


Пример с трансляцией данных в шестнадцатеричном формате можно провести так же, но заменить команду на Destination или добавить еще один пайп на Repeater:

nc -l -p 4545 -o file

В результате будет создан файл, в котором можно будет обнаружить передаваемые данные в шестнадцатеричном формате:


Как видно из тестового сценария использования, netcat не дает контролировать практически ничего, кроме направления данных. Нет ни разграничения доступа к ресурсам, которые пересылаются, ни возможности без дополнительных ухищрений работать с двумя сокетами, ни возможности контролировать действия сокета. Протестируем socat.

socat

STDIO -> TCP Socket;

FILE -> TCP Socket;

TCP Socket -> Custom Application;

UDP Socket -> Custom Application;

Для повседневного использования достаточно опций, но если понадобится когда-то работать напрямую с серийным портом или виртуальным терминалом, то socat тоже умеет это делать. Полный перечень опций можно вызвать с помощью команды:

Помимо редиректов socat также можно использовать как универсальный сервер для расшаривания ресурсов, через него можно как через chroot ограничивать привилегии и доступ к директориям системы.

Чтобы комфортно пользоваться этим инструментом, нужно запомнить шаблон командной строки, который ожидает socat:

socat additionalOptions addr1 addr2

additionalOptions - опции, которые могут добавлять возможности логирования информации, управления направлением передачи данных;

addr1 - источник данных или приемник (влияет использование флага U или u), это может быть сокет, файл, пайп или виртуальный терминал;

addr2 - источник данных или приемник (влияет использование флага U или u), это может быть сокет, файл, пайп или виртуальный терминал;

Попробуем провести трансляцию данных из сокета в сокет. Будем использовать для этого 1 машину. Перед началом эксперимента стоит отметить, что особенностью socat является то, что для его корректной работы нужно обязательно писать 2 адреса. Причем адрес не обязательно должен быть адресом, это может быть и приложение, и стандартный вывод на экран.

Например, чтобы использовать socat как netcat в качестве TCP сервера, можно запустить вот такую команду:

socat TCP-LISTEN:4545, STDOUT

Для коннекта можно использовать netcat:

nc localhost 4545


Настроим более тонко наш сервер, добавив новые опции через запятую после используемого действия:

socat TCP-LISTEN:4545,reuseaddr,keepalive,fork STDOUT

Дополнительные параметры распространяются на те действия, которые socat может выполнять по отношению к адресу. Полный список опций можно найти здесь в разделе "SOCKET option group".

Таким образом socat дает практически полный контроль над состоянием сокетов и расшариваемых ресурсов.

Статья написана в преддверии старта курса Network engineer. Basic. Всех, кто желает подробнее узнать о курсе и карьерных перспективах, приглашаем записаться на день открытых дверей, который пройдет уже 4 февраля.

Сокеты (англ. socket — разъём) — название программного интерфейса для обеспечения обмена данными между процессами. Процессы при таком обмене могут исполняться как на одной ЭВМ, так и на различных ЭВМ, связанных между собой сетью. Сокет — абстрактный объект, представляющий конечную точку соединения.

Принципы сокетов¶

Каждый процесс может создать слушающий сокет (серверный сокет) и привязать его к какому-нибудь порту операционной системы (в UNIX непривилегированные процессы не могут использовать порты меньше 1024). Слушающий процесс обычно находится в цикле ожидания, то есть просыпается при появлении нового соединения. При этом сохраняется возможность проверить наличие соединений на данный момент, установить тайм-аут для операции и т.д.

Каждый сокет имеет свой адрес. ОС семейства UNIX могут поддерживать много типов адресов, но обязательными являются INET-адрес и UNIX-адрес. Если привязать сокет к UNIX-адресу, то будет создан специальный файл (файл сокета) по заданному пути, через который смогут сообщаться любые локальные процессы путём чтения/записи из него (см. Доменный сокет Unix). Сокеты типа INET доступны из сети и требуют выделения номера порта.

Обычно клиент явно подсоединяется к слушателю, после чего любое чтение или запись через его файловый дескриптор будут передавать данные между ним и сервером.

Основные функции¶

socket()¶

Создаёт конечную точку соединения и возвращает файловый дескриптор. Принимает три аргумента:

domain указывающий семейство протоколов создаваемого сокета

  • AF_INET для сетевого протокола IPv4
  • AF_INET6 для IPv6
  • AF_UNIX для локальных сокетов (используя файл)

type

  • SOCK_STREAM (надёжная потокоориентированная служба (сервис) или потоковый сокет)
  • SOCK_DGRAM (служба датаграмм или датаграммный сокет)
  • SOCK_RAW (Сырой сокет — сырой протокол поверх сетевого уровня).

protocol

Протоколы обозначаются символьными константами с префиксом IPPROTO_* (например, IPPROTO_TCP или IPPROTO_UDP). Допускается значение protocol=0 (протокол не указан), в этом случае используется значение по умолчанию для данного вида соединений.

Функция возвращает −1 в случае ошибки. Иначе, она возвращает целое число, представляющее присвоенный дескриптор.

Пример на Python

Связывает сокет с конкретным адресом. Когда сокет создается при помощи socket(), он ассоциируется с некоторым семейством адресов, но не с конкретным адресом. До того как сокет сможет принять входящие соединения, он должен быть связан с адресом. bind() принимает три аргумента:

  1. sockfd — дескриптор, представляющий сокет при привязке
  2. serv_addr — указатель на структуру sockaddr, представляющую адрес, к которому привязываем.
  3. addrlen — поле socklen_t, представляющее длину структуры sockaddr.

Возвращает 0 при успехе и −1 при возникновении ошибки.

Пример на Python

Автоматическое получение имени хоста.

listen()¶

Подготавливает привязываемый сокет к принятию входящих соединений. Данная функция применима только к типам сокетов SOCK_STREAM и SOCK_SEQPACKET. Принимает два аргумента:

  1. sockfd — корректный дескриптор сокета.
  2. backlog — целое число, означающее число установленных соединений, которые могут быть обработаны в любой момент времени. Операционная система обычно ставит его равным максимальному значению.

После принятия соединения оно выводится из очереди. В случае успеха возвращается 0, в случае возникновения ошибки возвращается −1.

Пример на Python

accept()¶

Используется для принятия запроса на установление соединения от удаленного хоста. Принимает следующие аргументы:

  1. sockfd — дескриптор слушающего сокета на принятие соединения.
  2. cliaddr — указатель на структуру sockaddr, для принятия информации об адресе клиента.
  3. addrlen — указатель на socklen_t, определяющее размер структуры, содержащей клиентский адрес и переданной в accept(). Когда accept() возвращает некоторое значение, socklen_t указывает сколько байт структуры cliaddr использовано в данный момент.

Функция возвращает дескриптор сокета, связанный с принятым соединением, или −1 в случае возникновения ошибки.

Пример на Python

connect()¶

Устанавливает соединение с сервером.

Некоторые типы сокетов работают без установления соединения, это в основном касается UDP-сокетов. Для них соединение приобретает особое значение: цель по умолчанию для посылки и получения данных присваивается переданному адресу, позволяя использовать такие функции как send() и recv() на сокетах без установления соединения.

Загруженный сервер может отвергнуть попытку соединения, поэтому в некоторых видах программ необходимо предусмотреть повторные попытки соединения.

Возвращает целое число, представляющее код ошибки: 0 означает успешное выполнение, а −1 свидетельствует об ошибке.

Пример на Python

Передача данных¶

Для передачи данных можно пользоваться стандартными функциями чтения/записи файлов read и write, но есть специальные функции для передачи данных через сокеты:

Сокеты Unix — это форма связи между двумя процессами, которая отображается в виде файла на диске. Этот файл может использоваться другими программами для установления очень быстрых соединений между двумя или более процессами без каких-либо сетевых накладных расходов.


Что такое сокеты?

Сокеты — это прямая связь между двумя процессами. Представьте, что вы хотите позвонить своему другу по дороге; вы можете сделать звонок, направив его через вашу телефонную компанию и обратно в их дом, или вы можете провести провод прямо в их дом и отключить посредника. Последнее, очевидно, непрактично в реальной жизни, но в мире Unix очень распространено устанавливать эти прямые связи между программами.

Собственное имя для сокетов unix — сокеты домена Unix (Unix Domain Sockets), потому что все они находятся на одном компьютере. В некотором смысле сокеты — это сеть, полностью содержащаяся в ядре; вместо того, чтобы использовать сетевые интерфейсы и соответствующие накладные расходы для отправки данных, те же самые данные могут быть отправлены напрямую между программами.

Несмотря на создание файлов на диске, сокеты Unix на самом деле не записывают данные, которые они отправляют на диск, так как это было бы слишком медленно. Вместо этого все данные хранятся в памяти ядра; единственная цель файла сокета — поддерживать ссылку на сокет и давать ему разрешения файловой системы для управления доступом. В современных системах сокеты обычно расположены в директории /usr/lib/systemd/system/. Например, сокет MariaDB обычно находится по адресу:


Этот файл ничего не содержит, и вы не должны изменять его напрямую, за исключением разрешений, где это применимо. Это просто имя.

Как работают сокеты?

Сокеты просто предоставляют фактическое оборудование для перемещения данных. Сокеты на основе 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, вы также можете использовать сокет. Обычно вы подключаетесь к host:port из удалённой системы, но если вы подключаетесь к базе данных на том же сервере (например, REST API обращается к базе данных), вы можете использовать сокеты для ускорения. Это не повлияет на нормальное использование, но очень заметно при нагрузке, более 20% на 24 ядрах высокого класса со 128 одновременными пользователями и миллионом запросов в секунду. Увидите ли вы выгоду от сокетов при таких условиях — это совсем другое дело, но на этом этапе, вероятно, всё равно придётся заняться репликацией и балансировкой нагрузки.

Если вы хотите работать с сокетами вручную, вы можете использовать утилиту socat, чтобы открыть их через сетевые порты:

Это технически противоречит назначению сокетов домена Unix, но может использоваться для отладки на транспортном уровне.

Читайте также: