在物联网中,很多时候单打独斗是成不了事的,因此各个设备之间必须互相协作,这就要求设备能够互相知道彼此。要做到这一点,首先设备必须联网。在前面物联网学习(2)——通信技术中,我们提到了很多联网技术,这个就是基础。在需要各个设备互相协作的场景中,通常是使用WiFi。
各个设备都连接到网络之后,还需要能够发现彼此,并进行通信,因此引入了零配置组网(Zero Configuration Networking, ZEROCONF)的技术。现在的WiFi路由器通常都提供了DHCP(Dynamic Host Configuration Protocal,动态主机配置协议),这个协议能够给连接到WiFi的设备自动分配IP地址,这是每个设备在网络中的唯一标识。
下图是DHCP协议中,设备作为客户端与作为服务器的路由器之间的通信过程的示意图:
注意,上述的通信过程,是通过UDP传输协议来完成的。
有了DHCP的支持,设备接入WiFi之后,就能够自动获取IP地址,同时得到路由器的地址和DNS服务器的地址。
6.1 如何发现其他的设备
设备连接到WiFi之后,怎么自动发现其他的设备呢?或者说,怎样被其他的设备自动发现呢?
这就需要另外一个协议——UPnP协议的支持。UPnP协议的全称就是Universal Plug and Plan,统一即插即用协议。这个协议的目标就是实现网络设备的即插即用。
下图是UPnP协议的分层示意图:
设备之间的相互自动发现是通过第三层(从下往上数)的SSDP模块来实现的。这一层中的模块属于传输协议层,它们采用HTTP,HTTPU,HTTPMU协议,传输经过特殊封装的XML文件。
SSDP(Simple Service Discovery Protocol,简单服务发现协议)支持了设备的自动发现功能,因为一个设备就是一个服务。
要发现其他的设备/服务,可以使用SSDP的M-SEARCH方法来查询设备,从设备的响应中读取设备的服务能力的描述。如果要让其他的设备发现自己,在连接到WiFi后,可以通过SSDP发送NOTIFY方法,向网络中其他的设备/服务宣告自身的加入。
下面是一个UPnP组播包的例子:
NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
CACHE-CONTROL: max-age=66
LOCATION: http://192.168.31.188:49152/description.xml
NT: urn:schemas-upnp-org:service:ConnectionManager:1
NTS: ssdp:alive
SERVER: Linux/3.14.29, UPnP/1.0, Portable SDK for UPnP devices/1.6.13
USN: uuid:F7CA5454-3F48-4390-8009-483842e84c17::urn:schemas-upnp-org:service:ConnectionManager:1
可以看到,这个组播包是一个NOTIFY消息,通过1900端口,使用Http1.1协议发送的。通常这个包会每隔几秒发送一次。
我们不必自己来实现UPnP协议,有以下一些现成的开源库可以选择:
6.2 不使用UPnP可以吗?
可以不使用UPnP吗?答案是可以,我们还有一些其他的协议可以代替。最常用的就是mDNS和DNS-SD协议。苹果设备的AirDrop使用的Bonjour服务就是它们的具体实现。
非WiFi环境怎么办?
在非WiFi环境中,例如蓝牙和ZigBee设备,怎么组网?通常来说,这样的设备要依赖各个厂家定制的私有协议,例如小米的Mibeacon协议。行业内也有一些组织开始主导开放协议,例如AllJoyn协议,但是都还没有达到广泛使用的程度。