This is a very quick post.

In one of my current projects I wrote a macOS app that runs an embedded HTTP server and publishes itself as a Bonjour service. This can be easily done with an awesome library called CocoaHTTPServer. And from an iOS app that works with this macOS app, I need to browse available Bonjour services in current network and resolve their IP addresses and ports.

There’s no much resources on internet about this. Apple has some example code like BonjourWeb, but I like examples that have been reduced to their minimum essential, so I am writing this for my future reference, and for others who might need it.

ViewController.h

1
2
3
4
5
#import <UIKit/UIKit.h>
@interface ViewController<NSNetServiceBrowserDelegate, NSNetServiceDelegate>
@end

ViewController.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#import "ViewController.h"
#include <arpa/inet.h>
#include <netinet/in.h>
@interface ViewController ()
@property NSNetService *service;
@property NSNetServiceBrowser *browser;
@property NSMutableArray *services;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_services = [NSMutableArray new];
_browser = [NSNetServiceBrowser new];
_browser.delegate = self;
[_browser searchForServicesOfType:@"_http._tcp." inDomain:@""];
}
- (void)netServiceBrowser:(NSNetServiceBrowser *)browser didFindService:(NSNetService *)service moreComing:(BOOL)moreComing {
NSLog(@"got service");
NSLog(@"%@", service);
[_services addObject:service];
NSLog(@"resolving address");
[self resolveIPAddress:service];
}
- (void)resolveIPAddress:(NSNetService *)service {
NSNetService *remoteService = service;
remoteService.delegate = self;
[remoteService resolveWithTimeout:0];
}
- (void)netServiceDidResolveAddress:(NSNetService *)sender {
NSData *address;
struct sockaddr_in *socketAddress;
NSString *ipString;
NSInteger port;
for(int i=0; i < sender.addresses.count; i++){
address = sender.addresses[i];
socketAddress = (struct sockaddr_in *) address.bytes;
ipString = [NSString stringWithFormat: @"%s", inet_ntoa(socketAddress->sin_addr)];
port = sender.port;
NSLog(@"Resolved: %@-->%@:%@", sender.name, ipString, @(port));
}
}
@end