Передача UDP с использованием GCDAsyncUdpSocket через все доступные сетевые интерфейсы
Я использую GCDAsyncUdpSocket для трансляции UDP-пакетов для поиска на моих устройствах NAS.
Ниже приведен фрагмент кода для отправки и получения пакетов UDP.
NSString *broadCastAddress = @"255.255.255.255";
NSInteger udpPort = 8097;
GCDAsyncUdpSocket *gcdAsyncUdpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:selfdelegateQueue:dispatch_get_main_queue()];
[gcdAsyncUdpSocket bindToPort:udpPort error:&error];
[gcdAsyncUdpSocket setPreferIPv4];
NSData *data = @“Hi there”; // Sample data
[gcdAsyncUdpSocket enableBroadcast:YES error:&error];
[gcdAsyncUdpSocket beginReceiving:&error];
[gcdAsyncUdpSocket sendData:data toHost:broadCastAddress port:udpPort withTimeout:-1 tag:1];
Приведенный выше код может отправлять пакеты только через один сетевой интерфейс, т. Е. Через Wi-Fi, Ethernet или Thunderbolt. Я хочу транслировать все доступные сетевые интерфейсы. (Ethernet, WiFi, Thunderbolt и т. Д.).
Есть ли способ вещать через все доступные сетевые интерфейсы (Ethernet, WiFi, Thunderbolt и т. Д.) Одновременно и используя один и тот же порт.
Любая помощь приветствуется, спасибо заранее.
1 ответ
Уф!! Я нашел решение после множества методов поиска и проб и ошибок. Здесь идет решение.
Сначала перечислите все доступные сетевые интерфейсы, используя функцию ниже.
- (NSMutableArray *) enumerateAndGetDetailsOfAllNetworkInterfaces { NSMutableArray *interfaceArray = [[NSMutableArray alloc] init]; struct ifaddrs *ifap, *ifa; struct sockaddr_in *sa; char *addr; getifaddrs (&ifap); for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family==AF_INET) { QNInterfaceModel *interfaceModel = [[QNInterfaceModel alloc] init]; sa = (struct sockaddr_in *) ifa->ifa_addr; addr = inet_ntoa(sa->sin_addr); printf("Interface: %s\tAddress: %s\n", ifa->ifa_name, addr); interfaceModel.interfaceName = [NSString stringWithCString:ifa->ifa_name encoding:NSUTF8StringEncoding]; interfaceModel.interfaceIPAddress = [NSString stringWithCString:addr encoding:NSUTF8StringEncoding]; [interfaceArray addObject:interfaceModel]; } } freeifaddrs(ifap); return interfaceArray; }
Я создал InterfaceModel, которая хранит имя интерфейса и его адрес.
Шаг 2. Создайте сокет для каждого интерфейса
NSMutableArray *interfaceArray = [self enumerateAndGetDetailsOfAllNetworkInterfaces];
for(QNInterfaceModel *interfaceModel in interfaceArray)
{
NSError *error;
NSInteger udpPort = 8097;
GCDAsyncUdpSocket *gcdAsyncUdpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self
delegateQueue:dispatch_get_main_queue()];
[gcdAsyncUdpSocket bindToPort:udpPort interface:interfaceModel.interfaceName error:&error];
gcdAsyncUdpSocket.delegate = self;
if(error == nil)
{
[_socketArray addObject:gcdAsyncUdpSocket];
}
}
Шаг 3: Сохраните все созданные сокеты в массиве и выполните широковещательную рассылку через каждый из них, как показано ниже, но перед трансляцией нам нужно создать сокет прослушивателя для получения ответных пакетов.
NSError *error;
NSString *broadCastString = @"255.255.255.255";
NSInteger udpPort = 8097;
GCDAsyncUdpSocket *listenerGCDAsyncUdpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self
delegateQueue:dispatch_get_main_queue()];
[listenerGCDAsyncUdpSocket bindToPort:udpPort error:&error];
[listenerGCDAsyncUdpSocket setPreferIPv4];
[listenerGCDAsyncUdpSocket enableBroadcast:YES error:&error];
[listenerGCDAsyncUdpSocket beginReceiving:&error];
// Send Packets through all the available Interfaces
for(NSInteger i =0 ; i<_socketArray.count ;i++)
{
GCDAsyncUdpSocket *gcdAsyncUdpSocket = [_socketArray objectAtIndex:i];
gcdAsyncUdpSocket.delegate = self;
if(error)
{
// Error connecting
}
else
{
[gcdAsyncUdpSocket setPreferIPv4];
NSData *data = @"Hi There";
if (![gcdAsyncUdpSocket enableBroadcast:YES error:&error]) {
QNDLog(@"Error enableBroadcast:%@",error);
return;
}
[gcdAsyncUdpSocket beginReceiving:&error];
[gcdAsyncUdpSocket sendData:data toHost:broadCastString port:udpPort withTimeout:-1 tag:i];
}
}