Несколько приложений, использующих одну и ту же группу многоадресной рассылки на одном хосте Windows

Несколько приложений, использующих одну и ту же группу многоадресной рассылки на одном хосте Windows

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

Моя цель — иметь возможность свободно выбирать, на каких хостах запускать те или иные исполняемые файлы, и они будут обнаруживать всех своих коллег (будь то на том же хосте или на других хостах) без каких-либо предопределенных знаний.

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

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

  2. Если я запускаю разные процессы для отправки и получения, то принимающий процесс ничего не получает, несмотря на сообщение о присоединении к группе и все датаграммы отображаются в Wireshark.

  3. Сценарий, описанный в пункте 2, работает, если я перед прослушиванием также использую тот же сокет для отправки пакета в группу многоадресной рассылки, к которой я присоединился. Затем последняя получает многоадресные датаграммы в течение неопределенного периода времени, после чего просто прекращает прием датаграмм (она продолжает ждать поступления датаграмм). Датаграммы подтверждаются отправленными в/из сети с помощью Wireshark.

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

Насколько я понимаю, многоадресная передача IP определяет только связь междухозяева, в то время как ОС несет ответственность за перенаправление входящих пакетов в соответствующийприложение. Поскольку пакеты всегда отображаются в Wireshark, даже если приложение их не получает, похоже, что Windows не справляется с обработкой входящих пакетов или, по крайней мере, с доставкой их соответствующим приложениям.

Я признателен, если кто-нибудь сможет подтвердить или опровергнуть мои доводы, а также указать мне правильное направление решения этой проблемы. Цель состоит в том, чтобы иметь возможность для нескольких приложений на одном хосте присоединиться к одному каналу многоадресной группы и также получать сообщения без необходимости отправлять "мусор" в многоадресную группу, чтобы они могли получать данные (обходной путь, описанный как пункт номер 4).

Я использую Java для реализации и могу, если потребуется, разместить MWE здесь. Однако я опасаюсь, что это может сместить фокус со сценария на программирование, которое здесь не является проблемой (насколько я могу судить).

решение1

OP просит предоставить метод обнаружения одноранговых узлов в сети без каких-либо сведений об этих узлах, согласноэтот источникmDNS требует как минимум знания имени хоста каждого однорангового узла.

В результате mDNS не является приемлемым решением этой проблемы в описанном виде.

Согласнона этот ответ, о многоадресной рассылке, то, о чем вы просили, возможно. Это подразумевает использование опции сокета SO_REUSEADDR. Когда вы используете эту опцию сокета, она позволяет нескольким сокетам прослушивать одну и ту же комбинацию адрес:порт, пока;

  1. Адрес является многоадресным адресом; и
  2. SO_RESUSEADDR устанавливается для каждого сокета, который пытается привязаться к комбинации адрес:порт.

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

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

import socket, struct

MCAST_GRP = ''
MCAST_PORT = 1234

MULTICAST_TTL = 2

def create_beacon_listener():

    sock = socket.socket(
        socket.AF_INET,
        socket.SOCK_DGRAM,
        socket.IPPROTO_UDP
    )
    sock.setsockopt(
        socket.SOL_SOCKET,
        socket.SO_REUSEADDR,
        1
    )
    sock.setblocking(0)

    sock.bind(( MCAST_GRP, MCAST_PORT ))

    multicast_grp_req = struct.pack(
        "4sl",
        socket.inet_aton(MCAST_GRP),
        socket.INADDR_ANY
    )

    sock.setsockopt(
        socket.IPPROTO_IP,
        socket.IP_ADD_MEMBERSHIP,
        multicast_grp_req
    )
    
    return sock

Приведенный выше код возвращает прослушивающий сокет на желаемом групповом адресе MCAST_GRP и порту MCAST_PORT. И да, MCAST_GRP установлен на пустую строку, что означает, что вы фактически прослушиваете все группы адресов многоадресной рассылки. Это, похоже, ограничение либо в Windows, либо в моих знаниях, вероятно, последнее.

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

Этот код можно повторно использовать несколько раз в одном и том же процессе, хотя я еще не проверял, могут ли несколько процессов успешно его использовать. Я тестировал с использованием фреймворка asyncio python, поэтому несколько сокетов прослушивают один и тот же поток.

Кстати, для кроссплатформенной поддержки вы также можете заставить этот код работать на операционных системах nix, и на этих системах вы можете установить MCAST_GRP на определенный адрес.

РЕДАКТИРОВАТЬ:

Недавно я наткнулся наэтот ресурс от MSчто дает пример, который, кажется, позволяет использовать определенный адрес группы multicast, а не привязываться ко всем. Он включает установку некоторых дополнительных опций в переменной multicast_grp_req. Также пример — это код C++, а не python, но они достаточно похожи, чтобы уловить суть.

Надеюсь это поможет :)

Связанный контент