• Mac&IOS Bonjour(转)


    +一般在进行Socket编程或者网络访问的时候,首先需要确认对方网络服务已经开启,且需要知道对方的域名或地址以及端口,然后才可以进行进一步操作。在互联网上好点,网络服务方一般常年开启,且一般IP地址是固定的,另由于DNS服务的存在,只要记住对方的域名便可以。但是在局域网,设备不一定连在上面,即使连上了,服务也不一定开了,每当设备连接到局域网的时候,IP地址一般都是动态分配的,所以情况变的复杂。Bonjour的存在便是苹果为了解决局域网设备间连接麻烦的问题。   
      5
    +直白的说Bonjour就是是一种协议,使得局域网中的计算机可以方便的发布服务,发现服务和连接服务,达到零配置([Zeroconf][link-zeroconf])的目的。
      6
    +[link-zeroconf]:http://zeroconf.org
      7
    +
      8
    +Zeroconf Working Group指出要实现零配置网络服务的3个要求:
      9
    +
      10
    +>+ IP地址
      11
    +>+ **名字** 到 **IP地址** 的转换(即使没有DNS服务器的情况下)
      12
    +>+ 发现网络中的服务
      13
    +
      14
    +对于第一个要求相关系统和设备可以直接支持的,如动态IP地址分配。   
      15
    +第二个要求则可以通过多播(UDP协议向局域网内一组机器发送数据)的方式发送 类似DNS查询的请求,开启着的网络服务收到之后便作出回应,告知自己的名字。   
      16
    +第三个要求则通过DNS-SD来实现
      17
    +
      18
    +Bonjour一般的工作模式便是:在同一个局域网中,一方开启服务,通过Bonjour接口将这个服务发布,服务搜索方在服务列表中便可以看到对应的设备的名字,选择设备便可以进行连接了。整个过程无需事先知道服务发布方的IP地址和端口号。   
      19
    +我们常用的软件如iTunes的共享,keynote的remote控制或者支持Bonjour协议的打印机都可以看到Bonjour的影子。
      20
    +
      21
    +
      22
    +###二.Bonjour的实现及使用
      23
    +从上面的描述可以看出,Bonjour的用途便是在局域网内发布服务和搜索服务。
      24
    +下面从实现层面讲解Bonjour。  
      25
    +
      26
    +|层次|名称|
      27
    +|:----|:----|
      28
    +|Foundation|NSNetService/NSNetServiceBroswer|
      29
    +|CoreFoundation|CFNetService/CFNetServiceBroswer|
      30
    +|Low-Level Socket Based API|dns_sd.h(The DNS Service Discovery API)|
      31
    +|Multicast DNS Responder|mDNSResponder (开源项目)|
      32
    +
      33
    +一般情况下我们使用Foundation这一层接口就可以了,也是最方便的。
      34
    +当然服务方在发布服务之前你得先启好网络服务,比如listening socket创建好,且开始侦听某个端口,关于socket编程的知识可以查看[Socket编程][link-socket]  
      35
    +
      36
    +[link-socket]:Socket编程.md   
      37
    +
      38
    +**1.发布服务**
      39
    +
      40
    +  netService = [[[NSNetService alloc] initWithDomain:@""
      41
    +                                                type:@"_test._tcp"
      42
    +                                                name:@""
      43
    +                                                port:port] autorelease];
      44
    +  if(netService != nil) {
      45
    +      [netService scheduleInRunLoop:[NSRunLoop currentRunLoop]
      46
    +                                 forMode:NSRunLoopCommonModes];
      47
    +      netService.delegate = self;
      48
    +      [netService publish];
      49
    +  }
      50
    +
      51
    +**2.浏览服务**
      52
    +  
      53
    ++ 创建Service Broswer, 需要指定service type和domain,得和发布服务时候的type对应。还得设置delegate,然后实现其delegate方法,以便发现了服务之后进行处理以及对发现的服务进行获取IP地址和端口的结果进行处理。
      54
    +
      55
    +
      56
    +    testServiceBrowser = [[NSNetServiceBrowser alloc] init];
      57
    +    testServiceBrowser.delegate = self;
      58
    +    [testServiceBrowser searchForServicesOfType:@"_test._tcp" inDomain:@""];
      59
    +
      60
    +
      61
    ++ 实现Service Broswer 的delegate方法,处理服务增加或减少的事件
      62
    +
      63
    +
      64
    +    //pragma mark NetServiceBroswer Delegate
      65
    +    - (void)netServiceBrowser:(NSNetServiceBrowser*)netServiceBrowser
      66
    +               didFindService:(NSNetService*)service
      67
    +                   moreComing:(BOOL)moreComing {
      68
    +        [netServiceArray addObject:service];
      69
    +        if (!moreComing) {
      70
    +            [serviceTableView reloadData];
      71
    +        }
      72
    +    }
      73
    +  
      74
    +    - (void)netServiceBrowser:(NSNetServiceBrowser*)netServiceBrowser
      75
    +             didRemoveService:(NSNetService*)service
      76
    +                   moreComing:(BOOL)moreComing {
      77
    +        [netServiceArray removeObject:service];
      78
    +        if (!moreComing) {
      79
    +            [serviceTableView reloadData];
      80
    +        }
      81
    +    }
      82
    +    
      83
    +    
      84
    ++ 连接服务
      85
    +
      86
    +上面发现的Net Service是不带IP地址和端口信息的。   
      87
    +从服务列表中选择一个已经发现的服务,进行Resolve,便可以获取服务的详细信息了。
      88
    +
      89
    +  - (IBAction)connect:(id)sender{
      90
    +      NSUInteger selectedRow = [serviceTableView selectedRow];
      91
    +      NSNetService *selectedServiece = [netServiceArray objectAtIndex:selectedRow];
      92
    +      selectedServiece.delegate = self;
      93
    +      [selectedServiece resolveWithTimeout:5.0];
      94
    +  }
      95
    +  
      96
    +Resolve成功
      97
    +
      98
    +  //NSNetService Delegate
      99
    +  - (void)netServiceDidResolveAddress:(NSNetService *)sender{
      100
    +        NSLog(@"service ip:%@ port:%d",sender.address,sender.port);
      101
    +    if ([sender getInputStream:&inputStream outputStream:&outputStream]) {
      102
    +        [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
      103
    +                                         forMode:NSDefaultRunLoopMode];
      104
    +        [outputStream open];
      105
    +        //发送数据
      106
    +        NSData *helloData = [@"Hello" dataUsingEncoding:NSUTF8StringEncoding];
      107
    +        [outputStream write:[helloData bytes] maxLength:[helloData length]];
      108
    +    }
      109
    +  }
      110
    +  
      111
    +上面的代码充分利用了输入输出流进行通信。如果你自己的使用socket的连接也是可以的,因为这个时候已经可以获取了对方的IP地址和端口了。
  • 相关阅读:
    安卓巴士诚招版主,希望各位巴友踊跃加入我们!
    android用户界面之菜单(Menu)教程实例汇总
    360将推出多款360用户特供手机
    安卓巴士最新精选文章,请您查阅
    android用户界面之SeekBar教程实例汇总
    Android OpenGL ES 开发教程小结
    android用户界面之按钮(Button)教程实例汇
    Seleniumwebdriver系列教程(5)————如何定位frame中的元素
    Seleniumwebdriver系列教程(10)————如何智能的等待页面加载完成
    Seleniumwebdriver系列教程(6)————如何捕获弹出窗口
  • 原文地址:https://www.cnblogs.com/lzjsky/p/2966039.html
Copyright © 2020-2023  润新知