Bonjour!实现零配置网络联网的解决方案

Bonjour!实现零配置网络联网的解决方案

背景

简单介绍一下项目对本地网络连接的需求:车机连接移动设备。

那我们如何进行连接呢。

  1. 首先我们想到的最简单的方法就是通过IP连接。

  2. UDP广播。

利用UDP广播我们能向同一本地网络所有设备发送一条消息,接收到信息后我们能够解析出发送方的端口和IP。

问题:

  1. 耗电问题。不断的UDP Broadcast 会耗费大量电源。
  2. 网络阻塞问题。因为UDP广播会对同一本地网络的所有Host都发送信息。过于密集的发送,有可能会造成网络的堵塞。
  3. 稳定性,UDP Socket可能会因为各种情况而中断。

什么是 Bonjour ?

bonjour 是苹果公司发布的一个基于 ZEROCONF 工作组 (IETF下属小组) 的工作,用于实现零配置网络联网的解决方案。Bonjour是基于IP层协议的。

Bonjour是Apple推出的零配置网络协议,主要的目的是在缺少中心服务器的情况下解决网络设备的IP获取,名称解析和服务发现等关键问题。

Bonjour可以做什么


Bonjour可以完成的工作主要是在缺少中心服务器的情况下解决IP获取,名称解析和服务发现这三个问题。

  • IP获取
    在传统网络环境下,设备的IP地址通过两种方式获取,一种是静态配置,通过手工方式为设备指定一个IP地址,一种是动态配置,设备通过路由器的DHCP服务获得动态的IP地址。
    在无中心服务器的网络环境下,没有中心服务器提供DHCP服务,用户手工配置IP地址也很不方便,这就需要一种新的方式来帮助设备获取IP地址,就是希望设备可以主动为自己指定一个可用的IP地址。
    在IPV6环境下,IPV6协议本身就提供了设备自指定IP地址的能力,所以实现很简单,直接使用IPV6的协议支持就可以了。
    在IPV4环境下,Bonjour使用了随机指定IP地址的方法,首先为设备随机指定一个属于本地网段的IP地址,然后检查该地址在本地是否有冲突,如果有冲突就随机生成另一个新的IP地址,直到找到可用IP地址为止。
    我在做测试的时候没有测试这部分,都是使用的DHCP的动态地址。以后有时间测试了这个部分后再和大家分享测试结果。
  • **名称解析**
    在传统网络环境下,名称和IP地址的对应关系是通过DNS服务解析的。当一个设备需要访问一个域名,如“www.abc.com”,设备将“www.abc.com”发给DNS服务器,服务器返回该域名对应的IP地址,设备再使用返回的IP地址对目标服务器进行访问。
    在没有中心服务器的网络环境中,没有DNS服务器提供域名解析服务,名称解析变成一个严重问题。针对这一问题,业界的解决方案是mDNS,中文叫“组播DNS”,在标准文档RFC6762中定义。
    “组播DNS”的原理很简单,当一个设备需要解析一个名称时,如“abc.local”,这个设备通过UDP协议向本地网络中的所有设备广播一个消息,问谁是“abc.local”,本地网络中如果有一个设备认为自己是“abc.local”,它就给出响应,说出自己的IP地址。
    因为“组播DNS”基于UDP协议,采用广播消息的方式,所以不需要一个中心服务器提供DNS解析服务就可以完成本地的名称解析。
    Bonjour也是基于mDNS协议的,不过Bonjour在mDNS协议上作了扩展,加强了设备响应“组播DNS”请求的能力。在Bonjour协议下,应用只需要对某个名称进行注册,就可以将响应“组播DNS”请求的工作交由底层处理。也就是说在Bonjour协议下,应用不需要侦听本地网络的“组播DNS”请求并进行响应,这些工作由底层系统完成。
    为了区分全球域名和本地域名,mDNS协议使用“.local.”作为本地域名的根域名。
  • **服务搜索(自动在网络搜索服务)**
    当一个提供服务的设备获取IP地址,并自我指定一个域名后,其实还是不能满足用户的需求。因为用户需要的是某种服务,如打印服务,web服务,用户并不关心这些服务对应的服务器名称和它的IP地址。
    为了让用户更容易发现本地网络中的各种服务,Bonjour为设备提供了服务发现的能力。
    Bonjour提供的“服务发现”能力基于一个简单直接的规定,就是提供服务的设备在按以下标准对服务进行注册:“名称.服务类型.传输协议类型.local.”,比如:“DamonWebServer._http._tcp.local.”,又比如“DummiesWebServer._http._tcp.local.”。
    这样,当一个设备使用希望查找http服务的时候,Bonjour会去查找本地网络中注册过的包含”_http”的服务,然后将结果返回给用户选择。这时用户面对的是“DamonWebServer”和”DummiesWebServer”,用户可以不去关心到底这两个web服务到底在那台设备上,该设备的IP地址是什么。
    ###如何使用Bonjour

对于最终用户来讲,Bonjour基本上是透明的,他们不需要了解如何去使用Bonjour,往往都是应用开发者去考虑如何使用Bonjour。
对于应用开发者来讲,他们需要考虑有两部分,一是如何作为Bonjour客户端去发现使用本地服务,二是如何作为服务端如何注册Bonjour服务

  • 如何作为Bonjour客户端去发现本地服务
    iOS开发可以使用NSNetService框架中的NSNetServiceBrowser类去发现本地服务。
    基本过程如下:
    首先创建NSNetServiceBrowser实例:
    1
    2
    3
        serviceBrowser = [[NSNetServiceBrowser alloc] init];
        serviceBrowser.delegate = self;
        [serviceBrowser searchForServicesOfType:@"_http._tcp." inDomain:@"local."];
1
2
 - (void)netServiceBrowser:(NSNetServiceBrowser *)netServiceBrowser didFindService:(NSNetService *)netService moreComing:(BOOL)moreServicesComing {

  • 如何作为服务端注册Bonjour服务
    要注册成为Bonjour服务,开发者可以直接创建NSNetService实例,
    并通过initwithDomain:type:name:port:方法进行初始化,指定服务的域,类型,名称和端口,样例代码如下:

    1
        service = [[NSNetService alloc] initWithDomain:@"local." type:@"_http._tcp." name:@"DamonWebServer" port:port];

    NSNetService创建成功后,可以通过setDelegate指定代理,同时通过publish方法发布注册服务:

    1
    2
            [service setDelegate:self];
            [service publish];

其中指定的代理需要遵从“NSNetServiceDelegate”协议,可以对服务发布成功,发布失败等事件。

正常来讲,如果需要发布一个服务,需要在发布服务之前准备好服务并启动它。不过NSNetService的publish方法并不依赖它所发布的服务,不管服务是否准备好,是否启动,NSNetService的publish都可以成功将服务发布出去,只不过服务发布出去后其它使用这个服务的客户端会发现这个发布出来的服务是个无效服务。

---------Thanks for your attention---------
0%