Как Unix Domain Sockets различает несколько клиентов? - PullRequest
57 голосов
/ 10 марта 2012

TCP имеет пары кортежей (IP-адрес / порт / тип), чтобы отличить одного клиента от другого.UDP передает клиенту IP и порт.Как домен unix отслеживает разных клиентов?

Другими словами, сервер создает сокет, привязанный к некоторому пути, скажем / tmp / socket.2 или более клиентов подключаются к / tmp / socket.Что происходит под этим, который отслеживает данные от client1 и client2?Я предполагаю, что сетевой стек не играет роли в доменных сокетах, поэтому ядро ​​выполняет всю работу здесь?

Существует ли формат протокола домена unix, такой как существует формат протокола IP и форматы TCP / UDP?Публикуется ли где-нибудь формат протоколов дейтаграмм доменных сокетов?Каждый Unix индивидуален или что-то вроде POSIX стандартизирует его?

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

1 Ответ

86 голосов
/ 10 марта 2012

Если вы создаете сокет PF_UNIX типа SOCK_STREAM и принимаете к нему соединения, то каждый раз, когда вы принимаете соединение, вы получаете новый файловый дескриптор (как возвращаемое значение системного вызова accept) , Этот файловый дескриптор считывает данные и записывает данные в файловый дескриптор в клиентском процессе. Таким образом, он работает так же, как соединение TCP / IP.

Нет «формата протокола домена unix». Там не должно быть, потому что сокет Unix-домена не может быть подключен к узлу через сетевое соединение. В ядре файловый дескриптор, представляющий ваш конец сокета Unix-домена SOCK_STREAM, указывает на структуру данных, которая сообщает ядру, какой файловый дескриптор находится на другом конце соединения. Когда вы записываете данные в свой файловый дескриптор, ядро ​​ищет файловый дескриптор на другом конце соединения и добавляет данные в буфер чтения этого другого файлового дескриптора. Ядру не нужно помещать ваши данные в пакет с заголовком, описывающим его назначение.

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

Если вы связываете путь с вашим клиентским сокетом перед тем, как подключиться к серверному сокету (или перед отправкой данных, если вы используете SOCK_DGRAM), то процесс сервера может получить этот путь, используя getpeername (для SOCK_STREAM). Для SOCK_DGRAM принимающая сторона может использовать recvfrom для получения пути передающего сокета.

Если вы не связываете путь, тогда процесс получения не может получить идентификатор, который однозначно идентифицирует одноранговый узел. По крайней мере, не в ядре Linux, которое я использую (2.6.18-238.19.1.el5).

...