Pregunta

I want to discover whether there is a server, which is listening to a specific port, in the LAN with unknown IP address with GCDAsyncUdpSocket. I will broadcast some message in the LAN, and if the server exists, it will feedback a message then i will know the server's IP address.

Now I try to use the the following code to do the work:

udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

if (![udpSocket bindToPort:18686 error:&error])
{
    [self logError:FORMAT(@"Error binding: %@", error)];
    return;
}

if (![udpSocket beginReceiving:&error])
{
    [self logError:FORMAT(@"Error receiving: %@", error)];
    return;
}

NSString *host = @"192.168.2.139"; // server IP i know
int port = 8585;
NSString *message = @"Hello";
NSData *data = [msg dataUsingEncoding:NSUTF8StringEncoding];
[udpSocket sendData:data toHost:host port:port withTimeout:-1 tag:tag];

If i set the host IP to server IP, its all right, server will response. But i want to broadcast to find the server IP, and i try to use "192.168.2.0","192.168.2.1","192.168.2.255","255.255.255.255", all above address can not broadcast.

I wonder which IP address i can use to broadcast in LAN with 192.168.2.*, and which IP address to broadcast if don't know the LAN IP domain? Any help will be appreciated.

¿Fue útil?

Solución

I checked the GCDAsyncUdpSocket.h and find the function named - (BOOL)enableBroadcast:(BOOL)flag error:(NSError **)errPtr; I add the following to the setupSocket

if (![udpSocket enableBroadcast:YES error:&error]) {
        [self logError:FORMAT(@"Error enableBroadcast:%@",error)];
        return;
}

Then broadcast works...

to my question, i checked the 192.168.2.* LAN broadcast IP is 192.168.2.255, and the unknown LAN broadcast IP is 255.255.255.255.

I don't know why we need to enable the broadcast in GCDAsyncUdpSocket to use a broadcast IP. Hope this will help others someday.

Otros consejos

I found the following (working) code useful to generate all of the potential broadcast addresses for all of the networks your computer is connected to:

+ (NSDictionary *)allNetworks {
    NSMutableDictionary *networkStates = [NSMutableDictionary new];
    SCDynamicStoreRef storeRef = SCDynamicStoreCreate(NULL, (CFStringRef)@"FindCurrentInterfaceIpMac", NULL, NULL);
    if (storeRef) {
        NSDictionary *interfaceInfo = CFBridgingRelease(SCDynamicStoreCopyValue(storeRef, CFSTR("State:/Network/Interface")));
        NSArray *primaryInterfaces = interfaceInfo[@"Interfaces"];
        for (NSString* interfaceName in primaryInterfaces) {
            NSString *interfaceStateKey = [NSString stringWithFormat:@"State:/Network/Interface/%@/IPv4", interfaceName];
            NSDictionary *ipv4State = CFBridgingRelease(SCDynamicStoreCopyValue(storeRef, (__bridge CFStringRef)interfaceStateKey));
            if (ipv4State != nil) {
                networkStates[interfaceName] = ipv4State;
            }
        }
        CFRelease(storeRef);
    }
    return networkStates;
}

The returned dictionary will have the network interface names as keys, and the values will be dictionaries that have the keys @"Addresses", @"BroadcastAddresses", and @"SubnetMasks" and arrays of strings as the values. To add this to your code, you'll need to include

#import <SystemConfiguration/SCDynamicStore.h>

and link against SystemConfiguration.framework.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top