IP_DROP_MEMBERSHIP Несоответствие поведения - PullRequest
0 голосов
/ 26 октября 2018

У меня есть сценарий использования, в котором я присоединяюсь к членству, используя IP_ADD_MEMBERSHIP, и через некоторое время мне приходится IP_DROP_MEMBERSHIP (непосредственно перед drop seq id был 1), а затем снова я присоединяюсь к членству, используя IP_ADD_MEMBERSHIP (для той же группы многоадресной рассылки). Я замечаю, что я получаю следующий пакет (seqid = 2), который, по моему мнению, не должен происходить, так как, согласно моему пониманию, IP_DROP_MEMBERSHIP должен прекратить получать пакеты udp и очистить используемый им сокет, и как только я присоединился к нему, это должно быть последний доступный пакет, и это поведение не соответствует, иногда я получаю только последний пакет.

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

Пожалуйста, помогите. Я использую Centos 7.4

1 Ответ

0 голосов
/ 27 октября 2018

Попробуйте установить IP_MULTICAST_ALL в 0. По умолчанию 1. 1. 1001 *

Объяснение: При IP_MULTICAST_ALL 0 ваша ОС будет фильтровать входящие UDP-пакеты по группам, к которым вы присоединились в данный момент, что вы ожидаете в своем описании.

Но это не стандартное поведение в Linux.

По умолчанию (с IP_MULTICAST_ALL = 1) принимается любых пакетов UDP, которые поступают в ваш сокет. При назначении 0.0.0.0 это будут все UDP-пакеты, которые машина получает для этого порта, многоадресная и одноадресная, независимо от того, присоединились ли вы к какой-либо группе многоадресной рассылки или нет. Это означает, что вы увидите все артефакты разницы между присоединением к многоадресной группе и выходом из нее и реальное IGMP-сообщение, отправленное вашей машиной, а также вы увидите все артефакты и ошибки всех маршрутизаторов и коммутаторов, которые есть в вашей локальной сети. Например, когда вы покидаете группу многоадресной рассылки, ваша ОС может решить вообще не отправлять соответствующее сообщение IGMP, например, из-за того, что какой-то другой сокет также прослушивает этот адрес многоадресной рассылки, или из-за того, что ОС решает выйти с задержкой. Это все вполне допустимо.

Кстати, когда вы связываетесь с многоадресным адресом в Linux, у него просто есть функция фильтрации и вообще нет функции привязки. После этого вы будете получать только пакеты UDP, предназначенные для этого конкретного IP-адреса многоадресной рассылки, независимо от того, присоединились ли вы также к другим группам многоадресной рассылки.

Относительно «очистки» сокета. Очереди пакетов за сокетом полностью выходят за рамки вашего приложения. Вы не можете влиять на состояние или поведение очереди (кроме чтения из очереди или нет) и не можете ожидать какого-либо конкретного поведения.

На практике я бы предложил: - Привязать к 0.0.0.0. - Присоединяйтесь и выходите из групп многоадресной рассылки соответствующим образом. - Проверьте целевой адрес каждого полученного вами UDP-пакета и выполните фильтрацию самостоятельно. Используйте IP_PKTINFO, чтобы получить адрес назначения для каждого пакета. - Ни в коем случае не полагайтесь на маршрутизаторы и коммутаторы, имеющие какое-либо явное и детерминированное поведение многоадресной маршрутизации. У большинства из них есть минутные перерывы для выхода из групп многоадресной рассылки. Это означает, что даже когда вы покинули многоадресную группу (и даже если вы не присоединились), вы можете продолжать получать многоадресный трафик в течение нескольких минут. Это маскирует ошибки в вашем коде и вызывает головную боль при попытке отладки.

Таким образом, вам не придется полагаться на поведение, зависящее от ОС, и вы полностью контролируете, что вы получаете, а что нет.

...