Сокет Домена Unix: Используя датаграммную коммуникацию между одним серверным процессом и несколькими клиентскими процессами

Я хотел бы установить соединение IPC между несколькими процессами на Linux. Я никогда не использовал сокеты UNIX прежде, и таким образом я не знаю, является ли это корректным подходом к этой проблеме.

Один процесс получает данные (восстановленный после форматирования, двоичный файл) и должен распределить эти данные через локальный сокет AF_UNIX с помощью датаграммного протокола (т.е. подобный UDP с AF_INET). Данные, отправленные с этого процесса на локальный сокет Unix, должны быть получены несколькими клиентами, слушающими на том же сокете. Количество получателей может варьироваться.

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

struct sockaddr_un ipcFile;
memset(&ipcFile, 0, sizeof(ipcFile));
ipcFile.sun_family = AF_UNIX;
strcpy(ipcFile.sun_path, filename.c_str());

int socket = socket(AF_UNIX, SOCK_DGRAM, 0);
bind(socket, (struct sockaddr *) &ipcFile, sizeof(ipcFile));
...
// buf contains the data, buflen contains the number of bytes
int bytes = write(socket, buf, buflen);
...
close(socket);
unlink(ipcFile.sun_path);

Эти возвраты записи-1 с errno, сообщающим о ENOTCONN ("Транспортная конечная точка не соединен"). Я предполагаю, что это вызвано тем, что никакой процесс получения в настоящее время не слушает этот локальный сокет, корректный?

Затем я пытался создать клиент, который соединяется с этим сокетом.

struct sockaddr_un ipcFile;
memset(&ipcFile, 0, sizeof(ipcFile));
ipcFile.sun_family = AF_UNIX;
strcpy(ipcFile.sun_path, filename.c_str());

int socket = socket(AF_UNIX, SOCK_DGRAM, 0);
bind(socket, (struct sockaddr *) &ipcFile, sizeof(ipcFile));
...
char buf[1024];
int bytes = read(socket, buf, sizeof(buf));
...
close(socket);

Здесь, связывать сбои ("Адрес, уже используемый"). Так, я должен установить некоторые опции сокета, или это обычно - неправильный подход?

Заранее спасибо за любые комментарии / решения!

34
задан BigMick 24 July 2010 в 09:55
поделиться

3 ответа

Вам следует изучить многоадресную IP-рассылку, а не что-нибудь в Unix-домене. Сейчас вы просто пытаетесь писать в никуда. И если вы подключитесь к одному клиенту, вы будете писать только этому клиенту.

Это работает не так, как вы думаете.

-2
ответ дан 27 November 2019 в 17:07
поделиться

Ближайшая причина вашей ошибки заключается в том, что write () не знает, куда вы хотите отправить данные на . bind () устанавливает имя вашей стороны сокета, т.е. где данные поступают из . Чтобы установить конечную сторону сокета, вы можете использовать connect () ; или вы можете использовать sendto () вместо write () .

Другая ошибка («Адрес уже используется») связана с тем, что только один процесс может привязать () к адресу.

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

В качестве альтернативы вы можете использовать локальную многоадресную рассылку IP вместо сокетов домена UNIX (сокеты домена UNIX не поддерживают многоадресную рассылку).

7
ответ дан 27 November 2019 в 17:07
поделиться

Не было бы проще использовать разделяемую память или именованные каналы? Сокет - это соединение между двумя процессами (на одной или другой машине). Это не метод массовой коммуникации.

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

-1
ответ дан 27 November 2019 в 17:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: