0

I'm hosting a service in a Mac application and connecting with an iOS app. While the iOS app will find the service, the service doesn't contain any addresses, so I can't connect a socket.

This is my hosting code on the Mac:

- (void)start {

    queue = dispatch_queue_create("KeyboardServer", DISPATCH_QUEUE_CONCURRENT);

    socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:queue];

    NSError *error = nil;

    if ([socket acceptOnPort:0 error:&error]) {

        service = [[NSNetService alloc] initWithDomain:@"local." type:@"_probonjore._tcp." name:@"TestServer" port:[socket localPort]];

        service.delegate = self;

        [service publish];

    } else {
        NSLog(@"Unable to create server");
    }
}

This is the connecting code on iOS:

- (BOOL)connectToServer:(NSNetService *)service {

    NSArray *addresses = service.addresses;

    socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:queue];

    for (NSData *address in addresses) {

        NSError *error;

        if ([socket connectToAddress:address error:&error]) {
            NSLog(@"Socket connected!");

            return true;
        }
    }

    return false;
}

The problem is, service.addresses is always empty and the loop instantly exits.

Lepidora
  • 31
  • 1
  • Is there any way to have it automatically choose a port, or do I just have to pick one at random and hope it won't be taken already? – Lepidora Mar 23 '19 at 20:01
  • I just checked and the socket library (GCDAsyncSocket) automatically picks a port if you pass it 0. The service is publishing on port 51417 last time I ran it. – Lepidora Mar 23 '19 at 20:05

1 Answers1

2

For anyone curious, I searched around and found a solution.

In the

- (void)netServiceBrowser:(NSNetServiceBrowser *)browser didFindService:(NSNetService *)service moreComing:(BOOL)moreComing

function, you need to:

  • Add the service to an array to stop the object being deallocated as soon as it goes out of scope
  • Set the delegate on the object so that you can respond to its address resolution
  • Call the function to make it resolve

Which looks like this:

- (void)netServiceBrowser:(NSNetServiceBrowser *)browser didFindService:(NSNetService *)service moreComing:(BOOL)moreComing {

    NSLog(@"Found Service %@", [service name]);

    [services addObject:service];

    [service setDelegate:self];

    [service resolveWithTimeout:5.0f];
}

You then want to implement

- (void)netService:(NSNetService *)sender didNotResolve:(NSDictionary *)errorDict

and

- (void)netServiceDidResolveAddress:(NSNetService *)service

To catch when the address either resolves or doesn't resolve.

Lepidora
  • 31
  • 1