Несогласованность поведения ip_drop_membership

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

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

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

0
0
132
1

Ответы 1

Попробуйте установить для IP_MULTICAST_ALL значение 0. По умолчанию - 1.

Объяснение: С 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, чтобы получить адрес назначения для каждого пакета. - Ни в коем случае не полагайтесь на маршрутизаторы и коммутаторы с очевидным и детерминированным поведением многоадресной маршрутизации. У большинства из них есть длительные минуты ожидания для выхода из групп многоадресной рассылки. Это означает, что даже когда вы покинули группу многоадресной рассылки (и даже если вы не присоединились), вы можете продолжать получать многоадресный трафик в течение нескольких минут. Это маскирует ошибки в вашем коде и вызовет головную боль при попытке отладить это.

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

Другие вопросы по теме