通过所有可用的网络接口使用 GCDAsyncUdpSocket 进行 UDP 广播
Posted
技术标签:
【中文标题】通过所有可用的网络接口使用 GCDAsyncUdpSocket 进行 UDP 广播【英文标题】:UDP broadcast using GCDAsyncUdpSocket through all available Network Interfaces 【发布时间】:2015-09-17 05:19:35 【问题描述】:我正在使用 GCDAsyncUdpSocket 广播 UDP 数据包以搜索我的 NAS 设备。
下面是发送和接收UDP数据包的代码sn-p
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];
上面的代码只能通过单个网络接口发送数据包,即 Wifi 或以太网或 Thunderbolt,问题是我想通过所有可用的网络接口进行广播。 (以太网、WiFi、Thunderbolt 等)。
有什么方法可以同时通过所有可用的网络接口(以太网、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:将所有创建的socket存储在一个数组中,并通过每个socket进行广播,如下所示,但在广播之前,我们需要创建一个监听socket来接收响应包。
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];
【讨论】:
以上是关于通过所有可用的网络接口使用 GCDAsyncUdpSocket 进行 UDP 广播的主要内容,如果未能解决你的问题,请参考以下文章