Bonjour 的理解

先提问几个问题

  1. 什么是 Bonjour?
  2. Bonjour 提供了哪些服务?
  3. Bonjour 的工作机制是什么样子的?
  4. Bonjour 实践
  5. Bonjour 异常分析

# 什么是 Bonjour

Bonjour 被认为是 0 网络配置,自动发现 PC,普通设备和 IP 网络服务的协议。Bonjour 使用工业标准的 IP 协议,允许一台设备在不需要输入对方 IP 地址或配置 DNS 服务器的情况下自动发现其他设备。特别是 Bonjour 不需要 DHCP 服务器就能使 IP 自动分配,同时无需 DNS 服务器能给 IP 命名,发现服务不需要额外的服务器。同时它是个开放的协议。

Bonjour, also known as zero-configuration networking, enables automatic discovery of computers, devices, and services on IP networks. Bonjour uses industry standard IP protocols to allow devices to automatically discover each other without the need to enter IP addresses or configure DNS servers. See the Bonjour Protocol Specifications section for more details on the underlying standards. Technical Q&A QA1690 Common QA for Bonjour (opens new window)

一个实际场景是,我的电脑想用使用打印机打印一些资料,Bonjour 可以使打印机自动连接到网络,同时给打印机分配一个 IP 地址,无需任何配置,相同网络下的电脑就可以发现这台打印机,并识别到打印机的 IP 地址,进而建立连接完成打印工作。而且如果你以后地址被动态分配的地址被改变了,Bonjour 还能继续发现新的地址。

# Bonjour 提供了哪些服务?

  1. addressing (向 host 分配 IP 地址)
  2. naming (使用名字代表 host 而不是 IP 地址)
  3. service discovery (自动发现网络中的服务)

# Bonjour 的工作机制是什么样子的?

其实就是说一下上面三个服务的实现机制

  1. 分配 IP 的原理,使用链路本地地址(link-local address) 来解决。

    IPv6 协议包含了这种技术。IPv4 是使用另外的实现来达到这个目的,IPv4 的实现原理是在本地链路中随机取一个地址然后测试是不是被占用,如果没有占用则分配其为本地链路地址,否则重新生成并继续测试占用情况。 link-local address 这项技术被绝大多数操作系统实现,如果硬件厂商想要使用 Bonjour 服务也必须在自己的设备里实现这项技术。

对 link-local address 有兴趣的可以看下它的 wiki (opens new window)

  1. 在本地网络中解决 IP 到名字的转换的合适方案是使用 Multicast DNS (mDNS)

    具体实现原理是使用 IP 多播的方式在本地网络中发送 DNS 格式的查询,因为没有一个统一的 DNS 服务器去响应这些查询,所以每个设备或者服务都会去返回自己的 DNS 响应

    可以通过 Bonjour 提供的 API 注册服务,Bonjour 可以自动广播你的服务,任何查询你的服务的请求都会直接被转到正确的 IP 和端口。

    每个服务和设备都应该只有一个名字,这个名字只在当前的网络环境下起作用。这个起名字的过程大概是这样的

    1. 硬件厂商的设备通过发送带有自己名字(XYZ-LaserPrinter.local)的查询来看下是否当前网络中有一样的,如果有响应那就应该重新起个名字(XYZ-LaserPrinter-1.local 这个名字是在原来名字的基础上继续拼接了一个数字)如果没有则继续之前的操作。直到新的名字的查询没有响应。
    2. 软件服务是当注册的时候自己起一个名字,如果名字已经被使用了,则 Bonjour 协议会重新给它起一个。

    为了向系统表明 local host,macOS 上会在 local host 后面再加个点,比如 Steve.local.。 这部分命名规则比较复杂,这里不赘述了。

  2. 通过 DNS 发现服务的过程称为 DNS-SD(DNS Service Discovery)。发现服务这部分的内容还是建立在前面两部的基础上,一个指定服务类型和域名的 mDNS 查询发出去后,有符合条件的服务会返回它们的名字,结果包含了你可选择的一系列服务。和传统的查询服务不同,Bonjour 的服务更类似于询问「我想要的打印服务有没有」,而不是询问每个设备你在运行什么服务(Apple 官方对后者的的说明是,这种询问是以设备为中心的,而前者是以服务为中心)前者相比后者来说对 Client 更加有意义,Client 并不关心其他设备是干嘛的,不断询问只会造成网络压力。

# Bonjour 实践

macOS 系统提供了一个名为 dns-sd 的 Multicast DNS (mDNS) 和 DNS Service Discovery (DNS-SD) 测试工具。

一个例子,我想查看当前网络下能提供打印的服务

➜  ~ dns-sd -B _printer
Browsing for _printer._tcp
DATE: ---Thu 28 Dec 2017---
19:45:30.989  ...STARTING...
Timestamp     A/R    Flags  if Domain               Service Type         Instance Name
19:45:30.990  Add        3   5 local.               _printer._tcp.       Brother MFC-8510DN [30055c9332be] (2)
19:45:30.990  Add        2   5 local.               _printer._tcp.       Brother MFC-8510DN [30055c92a583] (2)

我啥都不指定是默认会列出当前提供 http 的服务

➜  ~ dns-sd -B
Browsing for _http._tcp
DATE: ---Thu 28 Dec 2017---
19:45:49.802  ...STARTING...
Timestamp     A/R    Flags  if Domain               Service Type         Instance Name
19:45:49.803  Add        3   8 local.               _http._tcp.          webserver (5)
19:45:49.804  Add        3   8 local.               _http._tcp.          bxxx

还有一个 Bonjour Browser 的软件(如图)来提供可视化的 Bonjour 服务浏览 Jietu20171228-195757

# 为啥有的时候连不上 Bonjour?

  1. 确认路由器开启了组播模式,某些路由器(如思科)默认关闭了「组播模式」,故无法在此网络下搜索到设备.
  2. 跟二次认证网络应该也没有关系.
  3. 如果是用 iPhone 设备有的时候跟 iOS 系统版本也有关系,参考 这里 (opens new window)

# 参考

  1. Technical Q&A QA1690 Common QA for Bonjour (opens new window)
  2. Bonjour Overview (opens new window)
  3. dns-sd (opens new window)