UniSet 2.32.1
Сетевой обмен на основе UDP (UNetUDP)

Общее описание

Обмен построен на основе протокола UDP. Основная идея заключается в том, что каждый узел на порту равном своему ID посылает в сеть UDP-пакеты содержащие данные считанные из локальной SM. Формат данных - это набор пар [id,value]. Другие узлы принимают их. Помимо этого данный процесс запускает "получателей" по одному на каждый (другой) узел и ловит пакеты от них, сохраняя данные в SM. При этом "получатели" работают на одном потоке с использованием libev (см. UNetReceiver).

В текущей версии поддерживается два протокола для обмена broadcast udp и multicast. Какой использовать протокол определяется в настроечной секции параметром unet_transport="broadcast" или unet_transport="multicast". По умолчанию "broadcast".

<UNetExchange name=".." unet_transport="broadcast" />

В зависимости от заданного протокола, будут использованы те или иные настройки.

При своём старте процесс считывает из секции <nodes> список узлов которые необходимо "слушать", а также параметры своего узла. Открывает по потоку приёма на каждый узел и поток передачи данных от своего узла. Помимо этого такие же потоки для резервных каналов, если они включены (см. Настройка резервного канала связи ).

Пример конфигурирования (UDP)

По умолчанию при считывании используется unet_broadcast_ip (указанный в секции <nodes>) и id узла - в качестве порта. Но можно переопределять эти параметры, при помощи указания unet_port и/или unet_broadcast_ip, для конкретного узла (<item>).

<nodes port="2809" unet_broadcast_ip="192.168.56.255">
<item ip="127.0.0.1" name="LocalhostNode" textname="Локальный узел" unet_ignore="1" unet_port="3000" unet_broadcast_ip="192.168.57.255">
<iocards>
...
</iocards>
</item>
<item ip="192.168.56.10" name="Node1" textname="Node1" unet_port="3001"/>
<item ip="192.168.56.11" name="Node2" textname="Node2" unet_port="3002"/>
</nodes>
Буфер для приёма сообщений можно настроить параметром \b recvBufferSize="1000" в конфигурационной секции
или аргументом командной строки \b --prefix-recv-buffer-size sz

Максимальное число сообщений вычитываемых из ести за один раз настраивается параметром recvMaxAtTime="5" или --prefix-recv-max-at-time num

Заметки
Имеется возможность задавать отдельную настроечную секцию для "списка узлов" при помощи параметра –prefix-nodes-confnode name. По умолчанию настройка ведётся по секции <nodes>

Чтобы отключить запуск "sender", можно указать nosender="1" в конкретного узла или непосредственно в настройках <UNetExchange nosender="1"...>

Пример конфигурирования (Multicast)

По умолчанию при считывании используется unet_multicast_ip и id узла - в качестве порта. Но можно переопределиять эти параметры, при помощи указания unet_multicast_port и/или unet_multicast_ip, у конкретного узла (<item>). При этом в параметре unet_multicast_ip должен быть задан адрес multicast-групы на которую будет подписываться каждый receiver и в которую будет писать соответствующий sender. По умолчанию для подключения к группе используется интерфейс ANY, но параметром unet_multicast_iface="192.168.1.1" можно задать интерфейс через который ожидаются multicast-пакеты. Поддерживается текстовое задание интерфейса в виде unet_multicast_iface="eth0"

Для указания ip для sender используется параметр unet_multicast_sender_ip="..", если он не задан, будет использован unet_multicast_iface="..".

Для посылающего процесса можно определить параметр unet_multicast_ttl задающий время жизни multicast пакетов. По умолчанию ttl=1. А так же определить ip для сокета параметром unet_multicast_iface. Можно задавать текстовое название интерфейса unet_multicast_iface="eth0", при этом в качестве ip будет взят первый ip-адрес из привязанных к указанному интерфейсу.

В данной реализации поддерживается работа в два канала. Соответствующие настройки для второго канала имеют индекс "2": unet_multicast_ip2, unet_multicast_port2, unet_multicast_iface2

Чтобы отключить запуск "sender", можно указать nosender="1" в конкретного узла или непосредственно в настройках <UNetExchange nosender="1"...>

В корневой секции <nodes..> можно задавать значения по умолчанию используемые для всех улов unet_multicast_ip, unet_multicast_iface, unet_multicast_sender_ip.

<nodes port="2809" unet_broadcast_ip="192.168.56.255" unet_multicast_ip="224.0.0.1 unet_multicast_iface="net1">
<item ip="127.0.0.1" name="LocalhostNode" textname="Локальный узел" unet_ignore="1">
<iocards>
...
</iocards>
</item>
<item id="3001" ip="192.168.56.10" name="Node1" textname="Node1"
unet_multicast_ip="224.0.0.1"
unet_multicast_iface="192.168.1.1"
unet_multicast_port2="3031"
unet_multicast_ip2="225.0.0.1"
unet_multicast_iface2="192.168.2.1">
...
</item>
<item id="3002" ip="192.168.56.11" name="Node2" textname="Node2">
unet_multicast_ip="224.0.0.2"
unet_multicast_iface="192.168.1.2"
unet_multicast_port2="3032"
unet_multicast_ip2="225.0.0.2"
unet_multicast_iface2="eth0">
...
</item>
</nodes>

Настройка резервного канала связи

В текущей реализации поддерживается возможность обмена по двум подсетям (Ethernet-каналам). Она основана на том, что, для каждого узла помимо основного "читателя", создаётся дополнительный "читатель" слушающий другой ip-адрес и порт. А так же, для локального узла создаётся дополнительный "писатель", который посылает данные в (указанную) вторую подсеть. Для того, чтобы задействовать второй канал, достаточно объявить в настройках переменные unet_broadcast_ip2. А также в случае необходимости для конкретного узла можно указать unet_broadcast_ip2 и unet_port2. Или в случае multicast unet_multicast_ip2 и unet_multicast_port2.

Переключение между "каналами" происходит по следующей логике:

При старте включается только первый канал. Второй канал работает в режиме "пассивного" чтения. Т.е. все пакеты принимаются, но данные в SharedMemory не сохраняются. Если во время работы пропадает связь по первому каналу, идёт переключение на второй канал. Первый канал переводиться в "пассивный" режим, а второй канал, переводится в "нормальный"(активный) режим. Далее работа ведётся по второму каналу, независимо от того, что связь на первом канале может восстановиться. Это сделано для защиты от постоянных перескакиваний с канала на канал. Работа на втором канале будет вестись, пока не пропадёт связь на нём. Тогда будет попытка переключиться обратно на первый канал и так "по кругу".

В свою очередь "писатели"(если они не отключены) всегда посылают данные в оба канала.

Регулирование частоты посылки

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

  • prefix_sendfactor="N" Где N>1 - задаёт "делитель" относительно sendpause определяющий с какой частотой информация о данном датчике будет посылаться. Например N=2 - каждый второй цикл, N=3 - каждый третий и т.п. При загрузке все датчики (относящиеся к данному процессу) разбиваются на группы пакетов согласно своей частоте посылки. При этом внутри одной группы датчики разбиваются по пакетам согласно заданному максимальному размеру пакета (см. конструктор класса UNetSender()).

Пауза между посылкой пакетов

Параметр --prefix-packsendpause или packsendpause в настаройках позволяет задать паузу (в миллисекундах) между посылками пакетов. Если итоговых пакетов с данными больше чем 1. При этом параметр --prefix-packsendpause-factor или packsendpauseFactor позволяет указать, что необходимо делать паузы не между каждым пакетом, а через каждый N пакет. По умолчанию packsendpause=5 миллисекунд.

Статистика работы канала

Для возможности мониторинга работы имеются счётчики, которые можно привязать к датчикам, задав их для соответствующего узла в секции '<nodes>' конфигурационного файла.

  • unet_lostpackets_id="" - общее количество потерянных пакетов с данным узлом (суммарно по обоим каналам)
  • unet_lostpackets1_id="" - количество потерянных пакетов с данным узлом по первому каналу
  • unet_lostpackets2_id="" - количество потерянных пакетов с данным узлом по второму каналу
  • unet_respond_id="" - наличие связи хотя бы по одному каналу
  • unet_respond1_id - наличие связи по первому каналу
  • unet_respond2_id - наличие связи по второму каналу
  • unet_numchannel_id="" - номер текущего активного канала
  • unet_channelswitchcount_id="" - количество переключений с канала на канал

Управление обменом

Для возможности внешнего управления приёмом и посылкой имеется возможность задать специальный датчик, позволяющий включать или отключать обмен. При этом датчики задаются отдельно для управления приёмом и для управления посылкой. Датчики прописываются в соответствующей секции '<nodes>' конфигурационного файла.

  • unet_recvmode_id="" - Датчик управления приёмом сообщений
  • unet_sendmode_id="" - Датчик управления посылкой сообщений

Полный перечень возможных значений см. UNetReceiver::Mode и UNetSender::Mode

Заметки
В случае необходимости управления и приёмом передачей одновременно, можно просто указать один и тот же управляющий датчик.