NSNetService

来源:互联网 发布:php初学者开发工具 编辑:程序博客网 时间:2024/06/15 21:58

这两个的概念不是我们讨论的内容。

首先,我们要分清楚NSNetService和NSNetServiceBrowser的作用。前者可以是服务提供者生成的一个服务,然后加到runloop中,并运行服务。这样后者就可以获取到该服务的动态,包括发现该服务,该服务移除等。但是发现是一个很轻量的操作,有点像HTTP中的head请求,并不会去获取body。同理,发现服务获取到的NSNetService也是不完整的,不包括txt data,address和port的,但是包括了其他信息,例如name,type,domain。我的验证似乎和http://stackoverflow.com/questions/6167850/nsnetservice-problems的说法有点出入,但是和下面官网的说法是一致的。

NSNetService

The NSNetService class represents a single service (either a remote service that your app wants to use or a local service that your app is publishing). Instances of this class are involved in all of the Bonjour operations described in this chapter.

NSNetService objects that represent remote services come preinitialized with the service name, type, and domain, but no host name, IP address or port number. The name, type, and domain are used to resolve the instance into the information needed to connect to the service (IP addresses and port number) upon request.

NSNetService objects used for publishing local services to the network must be initialized (by your code) with the service name, type, domain, and port number. Bonjour uses this information to announce the availability of your service over the network.

发现service只是开始,接着就要解析。解析有两种,一种是先发现,再对发现的service解析;还有一种是直接解析。

对于直接解析,就几行代码:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. _service = [[NSNetService alloc]initWithDomain:@"local." type:@"_marco._tcp" name:@"marco"];  
  2.         [_service setDelegate:self];  
  3.         [_service resolveWithTimeout:1.0];  
  4.         _services = [[NSMutableArray alloc]init];  
新建一个和publisher发出的service一样的service,然后设置代理,调用解析方法。

按需求实现代理方法,最关键的一个方法:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. - (void)netServiceDidResolveAddress:(NSNetService *)sender  
  2. {  
  3.     NSLog(@"%s",__func__);  
  4.     [_services addObject:sender];  
  5.     NSData *address = [sender.addresses firstObject];  
  6.     struct sockaddr_in *socketAddress = (struct sockaddr_in *) [address bytes];  
  7.     NSString *hostName = [sender hostName];  
  8.     Byte *bytes = (Byte *)[[sender TXTRecordData] bytes];  
  9.     int8_t lenth = (int8_t)bytes[0];  
  10.     const void*textData = &bytes[1];  
  11.     NSLog(@"server info: ip:%s, hostName:%@, text:%s, length:%d",inet_ntoa(socketAddress->sin_addr),hostName,textData,lenth);  
  12. }  

这边我们获取ip,host name,text和text的长度(这里可能需要参考http://www.zeroconf.org/Rendezvous/txtrecords.html)。这边我们用命令行来注册一个service,结果如下:


对于先发现后解析的情况,要实现browser的代理方法,这边比较关键的是didFindService,代码如下:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. - (void)netServiceBrowser:(NSNetServiceBrowser *)netServiceBrowser didFindService:(NSNetService *)netService moreComing:(BOOL)moreServicesComing {  
  2.     NSLog(@"%s",__func__);  
  3.     [_services addObject:netService];  
  4.     self.service = netService;  
  5.     [netService setDelegate:self];  
  6.     [netService resolveWithTimeout:1.0];  
  7. }  

这里因为ARC的问题,就用属性接收了下发现的service。然后调用resolve解析。结果和上面的一样。

最后,值得一提的是bonjour的目的是广播ip和port。因此直到目前,服务提供方和需求方并未开始直接点对点通信,知道ip和port之后,接下去是socket和stream的事情了。


提供些参考文献:

http://blog.csdn.net/cssmhyl/article/details/7920431

http://2009315319.blog.51cto.com/701759/1179965


0 0