Upgrade to Pro — share decks privately, control downloads, hide ads and more …

App-to-App Communication with Bonjour by Kevin ...

App-to-App Communication with Bonjour by Kevin Conner

Kevin discusses using Bonjour on iOS and Mac OS X at CocoaHeads Durham in May 2012

Triangle Cocoa

July 01, 2012
Tweet

More Decks by Triangle Cocoa

Other Decks in Programming

Transcript

  1. Bonjour • Deals with sockets • Selects ports for you

    • Listens for clients / Connects to servers • Sends and receives data
  2. Not! • Deals with sockets • Selects ports for you

    • Listens for clients / Connects to servers • Sends and receives data
  3. Bonjour • Publish a service you’re already running • Find

    published services • Resolve an address and a port
  4. Publish a service // TODO Get a socket to an

    open port // TODO Start listening for incoming connections // Publish the service NSNetService *netService = [[NSNetService alloc] initWithDomain:@"" type:@"_myservice._tcp" name:@"" port:port]; netService.delegate = self; [netService publish];
  5. Find published services NSNetServiceBrowser *browser = [[NSNetServiceBrowser alloc] init]; [browser

    setDelegate:self]; [browser searchForServicesOfType:@"_myservice._tcp" inDomain:@""]; - (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didFindService:(NSNetService *)aNetService moreComing:(BOOL)moreComing; - (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didRemoveService:(NSNetService *)aNetService moreComing:(BOOL)moreComing; - (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didNotSearch:(NSDictionary *)errorDict;
  6. Resolve address & port [netService setDelegate:self]; [netService resolveWithTimeout:5]; - (void)netServiceDidResolveAddress:(NSNetService

    *)sender { NSInputStream *is = nil; NSOutputStream *os = nil; [sender getInputStream:&is outputStream:&os]; // TODO open the streams } - (void)netService:(NSNetService *)sender didNotResolve: (NSDictionary *)errorDict;
  7. // TODO Get a socket to an open port //

    TODO Start listening for incoming connections
  8. Listening on a socket: NSSocketPort // Get a vacant socket

    port and start listening NSSocketPort *socketPort = [[NSSocketPort alloc] initWithTCPPort:0];
  9. Finding the port // Inspect the NSSocketPort to find the

    actual port number struct sockaddr *addr = (struct sockaddr *)[[socketPort address] bytes]; int port; if (addr->sa_family == AF_INET) { port = ntohs(((struct sockaddr_in *)addr)->sin_port); } else if (addr->sa_family == AF_INET6) { port = ntohs(((struct sockaddr_in6 *)addr)->sin6_port); }
  10. Accepting connections: NSFileHandle // Get a file handle to the

    socket NSFileHandle *fileHandle = [[NSFileHandle alloc] initWithFileDescriptor:[socketPort socket] closeOnDealloc:YES]; // Accept connections [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(connectionAccepted:) name:NSFileHandleConnectionAcceptedNotification object:fileHandle]; [fileHandle acceptConnectionInBackgroundAndNotify];
  11. Accepting connections: NSFileHandle - (void)connectionAccepted:(NSNotification *)notification { NSDictionary *userInfo =

    [notification userInfo]; NSFileHandle *clientSocketHandle = [userInfo objectForKey:NSFileHandleNotificationFileHandleItem]; NSNumber *errorNo = [userInfo objectForKey:@"NSFileHandleError"]; if (errorNo) { /* Handle it */ } // Keep listening for more connections [self.fileHandle acceptConnectionInBackgroundAndNotify]; if (clientSocketHandle) { // Save the client connection and start reading data [self.clientSocketHandles addObject:clientSocketHandle]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(clientSocketReadCompletion:) name:NSFileHandleReadCompletionNotification object:clientSocketHandle]; [clientSocketHandle readInBackgroundAndNotify]; } }
  12. Receiving data: NSFileHandle - (void)clientSocketReadCompletion:(NSNotification *)notification { NSDictionary *userInfo =

    [notification userInfo]; NSNumber *errorNo = [userInfo objectForKey:@"NSFileHandleError"]; if (errorNo) { /* Handle it */ } NSData *data = [userInfo objectForKey:NSFileHandleNotificationDataItem]; // TODO accumulate data, parse your protocol // Read more data when it becomes available [self.fileHandle readInBackgroundAndNotify]; }
  13. I know the pieces fit… • NSNetService & NSNetServiceBrowser •

    NSSocketPort & NSFileHandle • NSInputStream & NSOutputStream • Custom code for your app’s protocol
  14. KCSession • Server: Sets up socket, port, Bonjour, accepts connections

    • NSNetServiceBrowser is up to you • Client: Connects to a NSNetService • Sends and receives Cocoa objects