Как выбрать сетевой интерфейс, через который отправляется широковещательный пакет UDP - PullRequest
0 голосов
/ 03 февраля 2012

Если я отправлю UDP-пакет, содержащий 'foo', например:

socket = UDPSocket.new
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
socket.send('foo', 0, '<broadcast>', 40001)

, тогда wireshark сообщит мне, что пакет отправлен правильно, но, к сожалению, его адрес источника 192.168.0.3.Поскольку мой сервер прослушивает localhost: 40001, это означает, что он не получает пакет.Я не хочу, чтобы сервер слушал 0.0.0.0, поскольку он не должен получать аналогичные UDP-запросы, отправленные в другой сети.Я могу заставить сервер слушать в сети 192.168.0.0/24, но позже он будет прослушивать из другой сети, которая не является ни localhost, ни 192.168.0.0/24, так что это не решит проблему.

Есть ли способ выбрать адрес источника, с которого (и интерфейс через который) клиентский сокет отправит свой пакет?

Ответы [ 3 ]

2 голосов
/ 03 февраля 2012

Полагаю, вы пытаетесь отправить его на устройство обратной связи, поэтому должно быть что-то вроде (никогда не пробовал это с ruby):

dev="lo"
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BINDTODEVICE, dev+'\0'))

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

socket.setsockopt(Socket::SOL_SOCKET, Socket::IP_MULTICAST_LOOP, [1].pack('i'))
1 голос
/ 03 февраля 2012

Вы уже пробовали bind()?Вообще говоря, если вы socket.bind() обращаетесь к адресу (например, 127.0.0.1), то ваши пакеты должны отправляться с этого адреса.Зацикливание и широковещательные рассылки в этом отношении могут рассматриваться специально, но bind() будет моим первым выбором.

0 голосов
/ 24 апреля 2014

Ответ появляется на два года позже, но это может помочь будущим пользователям StackOverflow. Похоже, вам нужно использовать опцию сокета IP_MULTICAST_IF, которая принимает упорядоченную по сети версию DWORD вашего адреса интерфейса. К счастью, в библиотеке ipaddr есть служебный метод для преобразования удобочитаемых адресов:

address = '127.0.0.1'
hton = IPAddr.new(address).hton
socket.setsockopt(Socket::IPPROTO_IP, Socket::IP_MULTICAST_IF, hton)
...