Что касается моего общего вопроса, кажется, есть несколько способов сделать это:
Сложный способ изменения таблиц маршрутизации и взаимодействия каждого процесса. Это способ, который я описал выше. У него есть одно преимущество: он работает из пользовательского пространства. Я сделал несколько дополнительных заметок и ответил на мои конкретные вопросы ниже.
Напишите пользовательскую модель ядра, которая полностью игнорирует таблицу маршрутизации, если установлена SO_BINDTODEVICE
. Однако клиентский процесс все еще должен вызывать setsockopt(SOL_SOCKET, SO_BINDTODEVICE, dev)
. Этот вариант определенно не для слабонервных.
Виртуализируйте процесс. Это, вероятно, не подходит для многих людей, и это принесет собственный набор головной боли, в основном с конфигурацией. Но стоит упомянуть.
Параметры 1 и 2 требуют, чтобы процессы работали так, как нам хотелось бы. Это может быть частично облегчено созданием динамической библиотеки, которая перехватывает вызов socket () для создания сокета, а затем немедленно связывает его с устройством перед возвратом дескриптора. Это описано более подробно здесь .
После некоторого исследования и большого количества Google, я могу сделать несколько выводов о том, как ведет себя ядро Linux 2.6.26. Обратите внимание, что это, вероятно, все поведение, зависящее от реализации, и, возможно, даже ядро. Протестируйте свою собственную платформу, прежде чем принять решение о реализации функций, основанных на моей единой точке данных.
SO_BINDTODEVICE
действительно делает то, что говорит, по крайней мере для UDP.
Создаются уникальные IP-адреса для каждого интерфейса, так как мы используем таблицы маршрутизации. Пользовательский модуль ядра может обойти это ограничение.
Чтобы получать широковещательные рассылки по определенному интерфейсу, сначала выполните привязку к устройству, используя SO_BINDTODEVICE
, а затем привяжите к широковещательному адресу с помощью обычного вызова bind (). Привязка устройства должна быть сделана прежде всего. Затем сокет будет принимать только широковещательные сообщения, поступающие на этот интерфейс.
Я проверил это, сначала создав сокет. Затем я привязал его к определенному интерфейсу, используя setsockopt(SOL_SOCKET, SO_BINDTODEVICE, dev)
. Наконец, я связал его с широковещательным адресом. С другого компьютера я отправил широковещательную рассылку, которая будет получена через несвязанный интерфейс. Связанный с устройством сокет не получил эту трансляцию, что имеет смысл. Удалите вызов setsockopt(SOL_SOCKET, SO_BINDTODEVICE, dev)
, и трансляция будет принята.
Следует также отметить, что здесь вы также можете использовать setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
. Обратите внимание, что семантика SO_REUSEADDR
изменяется в зависимости от широковещательных адресов. В частности, допустимо иметь два сокета, привязанных к широковещательному адресу, и один и тот же порт на одном и том же компьютере, если они оба имеют SO_REUSEADDR
.
ОБНОВЛЕНИЕ: SO_BINDTODEVICE
с трансляциями, похоже, чревато опасностями, в частности, приемом кадров трансляции. Я наблюдал за широковещательными кадрами, полученными на одном интерфейсе, но одновременно исчезающими на другом. Похоже, что они влияют на локальную таблицу маршрутизации, но не зависят от правил политики IP. Тем не менее, я не уверен на 100% в этом и упоминаю это только в качестве предмета расследования, если вы хотите продолжить это. Все это, чтобы сказать: использовать на свой страх и риск. В интересах времени я открыл необработанный сокет на интерфейсе и сам проанализировал заголовки Ethernet и IP.