iOS_Bonjour编程总结二

简介

本文紧接上文iOS_Bonjour编程总结一,进一步描述Bonjour编程中客户端编写部分。

1. 浏览服务

我们可以使用NSNetServiceBrowser类来进行服务扫描,浏览服务不需要知道服务端的IP地址,端口等信息,只需要指定在某一个域名下搜索某种类型的服务。浏览服务的代码如下:

1
2
3
4
5
6
7
8
9
10
- (void)viewDidLoad {
[super viewDidLoad];
if (browser == nil) {
services = [NSMutableArray new];
browser = [[NSNetServiceBrowser alloc] init];
browser.delegate = self;
// 设置type, 和 domain, domain 一般为空,表示当前局域网环境。
[browser searchForServicesOfType:@"_associateHelp._tcp." inDomain:@""];
}
}

我们可以通过NSNetServiceBrowser的代理方法监听浏览服务过程中每个关键节点的的信息。如下:

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
#pragma mark - NSNetServiceBrowserDelegate
//即将开始扫描
- (void)netServiceBrowserWillSearch:(NSNetServiceBrowser *)browser {
NSLog(@"netServiceBrowserWillSearch");
}
//停止扫描
- (void)netServiceBrowserDidStopSearch:(NSNetServiceBrowser *)browser{
NSLog(@"netServiceBrowserDidStopSearch");
}
//发现服务,moreComing 用来判断还有没有服务过来。
- (void)netServiceBrowser:(NSNetServiceBrowser *)browser didFindService:(NSNetService *)service moreComing:(BOOL)moreComing {
NSLog(@"%@", service.name);
NSLog(@"%@", service.type);
NSLog(@"%ld", service.port);
NSLog(@"didFindService");
//测试代码,这里只有一个服务,我就直接做解析了。
[self connectToService:service];
}
//服务被移除
- (void)netServiceBrowser:(NSNetServiceBrowser *)browser didRemoveService:(NSNetService *)service moreComing:(BOOL)moreComing {
NSLog(@"%@", service.name);
NSLog(@"%@", service.type);
NSLog(@"didRemoveService");
}
- (void)netServiceBrowser:(NSNetServiceBrowser *)browser didNotSearch:(NSDictionary<NSString *, NSNumber *> *)errorDict {
NSLog(@"didNotSearch");
}
//下面两个方法是关于domain域变化的监听。
- (void)netServiceBrowser:(NSNetServiceBrowser *)browser didFindDomain:(NSString *)domainString moreComing:(BOOL)moreComing {
NSLog(@"didFindDomain");
}
- (void)netServiceBrowser:(NSNetServiceBrowser *)browser didRemoveDomain:(NSString *)domainString moreComing:(BOOL)moreComing {
NSLog(@"didRemoveDomain");
}

2. 解析服务

我在搜索到服务的时候就调用了

1
2
3
4
5
6
[self connectToService:service];
-(void)connectToService:(NSNetService *)service {
service.delegate = self;
//解析服务
[service resolveWithTimeout:5];
}

这个方法主要的作用是:在指定的时间内解析服务,解析成功调用NSNetServiceDelegate的netServiceDidResolveAddress, 解析失败调用didNotResolve。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#pragma NSNetServiceDelegate
-(void)netServiceDidResolveAddress:(NSNetService *)sender
{
NSInputStream *iStream;
NSOutputStream *oStream;
BOOL error = NO;
if (![sender getInputStream:&iStream outputStream:&oStream]) {
error = YES;
}
//inputstream
if (iStream != NULL) {
inputStream = iStream;
inputStream.delegate = self;
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
if (inputStream.streamStatus == NSStreamStatusNotOpen) {
[inputStream open];
}
}else{
error = YES;
}
}
- (void)netService:(NSNetService *)sender didNotResolve:(NSDictionary<NSString *,NSNumber *> *)errorDict
{}

3. 交互

在解析服务成功之后,我们就可以拿到服务端的input/output Stream了,之后就可以随意使用流操作进行读写操作。关于socket的使用,可以参考iOS_NSStream使用指南

参考资料

参考一:c语言中文网

参考二:slvher的博客

参考三:Apple : Stream Programming Guide

参考四:iOS网络高级编程