Как отправлять широковещательные пакеты UDP через все интерфейсы в Objective-C / OS X 10.8 (DHCP)

Я создаю небольшую утилиту, которая должна обслуживать IP-адрес и параметры по BOOTP на моем MacBook Pro.

Я использовал библиотеку AsyncUdpSocket из GitHub (спасибо RobbieHanson), и когда моя машина настроена только с подключенным проводным Ethernet (Airport Off), тогда он работает. Однако, как только я включаю свой Wi-Fi, все ответы на широковещательные рассылки переходят по интерфейсу Wifi. Это приводит к тому, что проводные клиенты не получают ответа.

Код инициализации / получения:

if (![socket bindToAddress:@"0.0.0.0" port:67 error:&err])
    NSLog(@"Error: unable to bind (%@)", [err localizedDescription]);
[socket enableBroadcast:YES error:&err];
[socket receiveWithTimeout:-1 tag:0];

Отправить код:

[sock sendData:packetData toHost:@"255.255.255.255" port:68 withTimeout:-1 tag:0];

Я уверен, что должен быть способ сделать это, но это моя первая программа для OS X, и я изо всех сил стараюсь освоить мой этикет для поиска в Google, чтобы он подходил фреймворкам:)

ОБНОВИТЬ

Сегодня вечером я испортил свой код и проверил, что делает AsyncUdpSocket, когда я его вызываю. По сути, у меня следующая ситуация; если я позвоню bindToAddress и поставка 10.0.0.1 (адрес назначен моей ETH NIC), тогда я не получаю никаких пакетов, и я не могу их отправить. Однако, если я пройду nil в метод, то я могу отправить сообщение и получить широковещательные сообщения - недостатком является то, что отправка происходит через мой WIFI NIC (маршрут по умолчанию)

На заднем плане - AsyncUdpSocket библиотека зовет CFSocketSetAddress либо с IFADDR_ANY, если указано значение nil, либо с заполненной структурой IFADDR 10.0.0.1, если она указана. Ошибки не выдаются, и поэтому следует ожидать, что сработает.

Есть идеи? Я иду вверх по стене и просто хочу, чтобы это было решено. Мне действительно нравится асинхронная природа библиотеки, поэтому я не хочу ее выбрасывать.

1 ответ

Решение

Я думаю, что вы должны

  1. Получить список всех сетевых интерфейсов на вашем компьютере,
  2. Для каждого интерфейса создайте сокет и привяжите его к адресу интерфейса.
  3. Отправить / получить на всех сокетах, по одному для каждого интерфейса.

Часть 1 может быть сделана, например, с getifaddrs() (введите "man getifaddrs" в Терминале). Я не знаю, есть ли в CoreFoundation более простая в использовании функция.

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