Reputation: 244
I am using GCDAsyncUdpSocket for broadcasting UDP packets for searching my NAS devices.
Below is the code snippet for sending and receiving UDP packets
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];
The above code can send packets through only single Network interface i.e either Wifi or Ethernet or Thunderbolt, the thing is i want to broadcast through all of the available Network Interfaces. (Ethernet, WiFi, Thunderbolt etc.).
Is there any way i can broadcast via all the available Network Interfaces (Ethernet, WiFi, Thunderbolt etc.) at the same time and using the same port.
Any help is appreciated, thanks in advance.
Upvotes: 2
Views: 1902
Reputation: 244
Phew!! I figured out a solution after lot of googling and trial & error methods. Here goes the solution.
First enumerate all the available Network interfaces using the below function.
- (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;
}
I have created InterfaceModel which stores the Interface Name and its Address.
Step 2: Create a Socket for each Interface
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];
}
}
Step 3: Store all the created sockets in a array and broadcast through each of them as follows, but before broadcasting, we need to create a listener socket to receive the response packets.
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];
}
}
Upvotes: 3