Передача 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 ответ

Уф!! Я нашел решение после множества методов поиска и проб и ошибок. Здесь идет решение.

  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];
    }
}
Другие вопросы по тегам