Группы каналов
Каналы, в которых сущность выступает сервером, могут быть объединены в одну или несколько групп.
Каждой группе каналов соответствует свой слушающий дескриптор (listener handle).
Два IPC-канала имеют одинаковое имя "second_connection_to_A" и объединены в группу. Еще один канал с именем "first_connection_to_A" не входит в эту группу. Обозначения: cl_1, cl_2, cl_3 — клиентские IPC-дескрипторы; srv_1 — серверный IPC-дескриптор; ls_1 — слушающий IPC-дескриптор.
Слушающий дескриптор позволяет серверу принимать запросы сразу по всем каналам из группы. При этом нет необходимости создавать отдельный поток на каждый канал — достаточно в одном потоке сервера выполнить системный вызов Recv()
, указав слушающий дескриптор.
Создание группы каналов с помощью init-описания
Чтобы каналы образовали группу, они должны соединяться с одной серверной сущностью и иметь одинаковые имена. Например, чтобы получить систему каналов, изображенную выше, можно использовать следующее init-описание:
init.yaml
entities:
# Сущность "A" выступает как сервер, поэтому ее список соединений пуст.
- name: A
# Сущность "B" будет соединена сущностью "A" двумя разными каналами.
- name: B
connections:
- target: A
id: first_connection_to_A
- target: A
id: second_connection_to_A
# Сущность "С" будет соединена с сущностью "A" каналом с именем
# "second_connection_to_A". Два канала с одинаковыми именами будут объединены
# в группу: на стороне сущности "A" они будут иметь один и тот же
# IPC-дескриптор (слушающий дескриптор ls_1).
- name: C
connections:
- target: A
id: second_connection_to_A
Обмен сообщениями в случае группы каналов
Рассмотрим, как происходит обмен сообщениями для группы каналов, описанной выше.
Клиентские сущности B
и C
получают значение клиентского дескриптора по имени соединения first_connection_to_A
и отправляют запрос:
entity_B.c, entity_C.c
…
// Получение клиентского IPC-дескриптора cl, соответствующего соединению " second_connection_to_A".
Handle cl = ServiceLocatorConnect("second_connection_to_A");
…
// Отправка запроса
Call(cl, &RequestBuffer, &ResponseBuffer);
…
Оба используемых канала имеют одно имя — second_connection_to_A
. Однако по этому имени сущности B
и C
получат разные значения дескрипторов: сущность B
получит значение cl_2
, а сущность C
— значение cl_3
.
Серверная сущность A
получает значение слушающего дескриптора ls_1
. Далее сущность A
ожидает запросы по двум каналам сразу (от B
и от C
), используя дескриптор ls_1
. После получения и обработки запроса сущность A
отравляет ответ, используя дескриптор ls_1
. Ответ будет отправлен тому клиенту, который инициировал запрос:
entity_A.c
…
nk_iid_t iid;
// Получение слушающего дескриптора ls_1, соответствующего соединению
"second_connection_to_A"
Handle ls_1 = ServiceLocatorRegister("second_connection_to_A", NULL, 0, &iid);
…
// Ожидание запроса от сущности B или C
Recv(ls_1, &RequestBuffer);
…
// Обработка поступившего запроса
…
// Отправка ответа тому клиенту, от которого пришел запрос
Reply(ls_1, &ResponseBuffer);
…