Выбор адаптера ethernet с помощью winsock в VS C++
У меня есть приложение, которое должно обнаруживать устройства, подключенные к ПК с Windows. Этот компьютер может иметь несколько адаптеров Ethernet. Это делается путем отправки широковещательного пакета UDP/IP, на который устройство отвечает. Обычно один адаптер подключен к глобальной сети, а другой-к локальной сети. Если Windows "использует" локальную сеть в качестве основного адаптера или адаптер WAN отключен, все идет хорошо. Если нет, то ответ не возвращается в приложение (Wireshark проверяет, что устройство получает и отвечает на запрос). Как заставить Windows использовать сетевой адаптер для широковещательной передачи запроса на обнаружение и получения ответа?
Что я уже пробовал:
Я пробовал несколько веб - поисков без каких-либо значимых результатов.
Rick York
Используя Wireshark с включенными обоими адаптерами, вы убедились, что сообщение выходит из них обоих? Находятся ли адреса адаптеров в разных подсетях или в одной и той же? Это может иметь огромное значение.
Gerry Schmitz
Почему вы не можете просто пинговать диапазон, чтобы "обнаружить"?
11917640 Member
Вам нужно привязать UDP-сокет к IP-адресу адаптера. Используя функцию GetIpAddrTable, вы можете перечислить все адаптеры и получить их адреса.
cwparker
The two adapters are connected to two different physical networks. For example, one adapter has an IP of 192.168.1.207 and the other has an IP of 172.28.74.254 (both with a subnet mask of 255.255.254.0). Windows thinks the adapter connected to 172.28.74.254 is the primary adapter. If the device is connected to the 172.28.74.x WAN, the app finds it. If it is connected to the 192.168.1.x LAN, it does not find it unless the 172.28.74.254 adapter is disabled. The IP address of the device is unknown, but for this example, let's say it's 192.168.1.2. It really doesn't matter what it's IP is. The problem is that the app can't find it if it isn't connected to the 'primary' adapter. For this app, there's no problem in having the user specify which adapter to use. It is a problem to disable the 'primary' adapter so that the device can be discovered on the 'secondary' adapter.
Да, я много чего перепробовал. Выбор IP-адреса адаптера с помощью функции bind() не работает. Я предполагаю, что это потому, что я пытаюсь отправлять и получать широковещательные пакеты.
Поскольку IP-адрес устройства полностью неизвестен (например, это может быть не 192.168.1.x, а 172.172.172.172), на самом деле невозможно пропинговать диапазон, чтобы обнаружить его.
Я знаю, что Wireshark каким-то образом умудряется позволить вам выбрать адаптер, который вы нюхаете, так что это должно быть возможно. Я просто не знаю, как это сделать.
Rick York
Я не уверен, что это поможет, но взгляните на MSTCPIP.h и функции GetAdaptersInfo() и SetAdaptersInfo(). Они могут помочь привести вас к тому, что вам нужно. Одна из возможностей состоит в том, чтобы использовать их и программно отключить адаптер, чтобы вы могли попробовать другой и найти машину.
cwparker
Ладно, я думаю, что разгадал тайну, но не проблему:
Перечисление всех адаптеров, чтобы получить их IP-адрес и использование bind() перед трансляцией запроса обнаружения действительно работает (как проверено Wireshark), но происходят 2 вещи, которые заставляют меня думать, что вещи не работают:
1) У меня работает Брандмауэр Symantec (действительно ненавижу его, но он навязывает его мне). Я обнаружил, что Symantec блокирует входящий широковещательный ответ с устройства, если оно не находится на основном адаптере! Если я отключу Symantec, он вроде как работает (см. 2).
2) запрос, отправленный на неосновной адаптер, эхом возвращается обратно. Таким образом, первый recv (), который вы делаете после запроса, возвращает запрос обратно (я проигнорировал, так как это был недопустимый ответ). Если я проверю это, выбросьте его и сделайте второй recv() Я получаю настоящий ответ! Странно, не нужно ли это делать на основном адаптере?
Так что я могу иметь дело с 2) но сейчас все, что я могу сделать, это сказать пользователю отключить свой брандмауэр, чтобы заставить его работать с 1).
Спасибо всем за вашу помощь в этом деле.
11917640 Member
Устройству не нужно использовать широковещательную передачу, оно может использовать sendto, имея IP-адрес отправителя.
cwparker
Unfortunately, the 'device' needs to broadcast it's response, otherwise the PC which is running the 'app' won't receive the response in the case where the 'device's IP address is 'logically' on another subnet than the PC's. For example, the PC's IP address may be 192.168.0.207 but the 'device's configured IP is 192.168.7.13 (both have a subnet mask of 255.255.255.0). Physically they're both on the same LAN (a switch will pass packets between them, switches don't care about subnet masks), but the PC will throw away a packet from the 'device' unless it's a broadcast (since the PC thinks it is from a different subnet). In this situation, I have no way to know what the 'device's configured IP address is, but I have to discover it, so that I can send a request for it to renumber itself to one that is on the same subnet as the PC (so then static IP packets will work).
Вся цель этого "приложения" состоит в том, чтобы перенумеровать IP-адрес "устройства". Типичное использование состоит в том, чтобы непосредственно подключить "устройство" к ПК, а затем запустить перенумерованное "приложение". Все работает хорошо, если компьютер пользователя имеет только один адаптер Ethernet или физический порт, к которому они подключают устройство, является "основным" адаптером. Это существующее "приложение", которое хорошо работает уже много лет. Только в последнее время все больше ноутбуков с адаптерами Wi-Fi идентифицируют порт Wi-Fi как основной адаптер, вызывающий сбой приложения. Я не могу изменить прошивку в устройстве, чтобы справиться с этим, поэтому я пытался обновить "приложение", чтобы справиться с этой ситуацией.