总体而言,SSDP协议规定了两种发现设备的途径:
第一种途径,控制端发送搜索设备消息,并监听响应消息;
第二种途径,控制端监听设备的宣告消息。
这两种只要有一种途径成功,就实现了设备发现。
抓包分析
以腾讯App发现XXX为例分析,假设两台设备加入局域网络后,手机获取了IP地址192.168.1.102,而XXX获取了IP地址192.168.1.112。
手机发送搜索设备消息,并监听响应消息
图1的tcpdump请求过程是192.168.1.102发现192.168.1.112,即手机发现XXX的过程.
首先192.168.1.102发了一个多播消息,消息地址是239.255.255.250:1900,基于HTTP/1.1协议;192.168.1.112收到了多播消息;并给192.168.1.102发了一条响应消息;携带了192.168.1.112的一些信息;如设备名称,设备描述文件位置,设备标识等。
192.168.1.102收到响应就会获得关于192.168.1.112的信息,这就实现了192.168.1.102对192.168.1.112的发现,即手机发现了XXX设备。
66和67两条消息是ARP消息,地址解析协议,根据地址192.168.1.102解析其MAC地址,用于网络层传输。
下面分析两条消息的报文结构。
手机发的搜索消息.
图2的tcpdump数据是192.168.1.02搜索消息的报文。
192.168.1.102每隔1s时间发一条SSDP消息到239.255.255.250:1900,请求行M-SEARCH * HTTP/1.1,有header,无body。
header携带了一些字段,解读如下:
ST(Search Target),搜索的目标是upnp:rootdevice;
MX等待响应的延时时间;
MAN消息的类型 "ssdp:discover"是搜索消息的必要值;
HOST多播地址和端口, 239.255.255.250:1900是必要值。
这条消息实现了搜索upnp:rootdevice设备。
手机收的响应消息。
图3的tcpdump是192.168.1.112收到这条M-SEARCH消息后响应的tcpdump抓包数据。
响应消息是一个UDP消息,有header,无body。由于SSDP消息使用的是HTTP/1.1,因此响应行时HTTP/1.1 200 OK。
header携带的消息解读如下:
Content-Type 内容类型;
Server 服务器名字;
Content-Length 字节单位的消息长度;
Cache-Control 告知客户端这条消息的缓存时长,以秒为单位;
EXT;
Date 服务器产生并发送该报文的日期和时间;
ST 搜索目标;
USN Unique Service Name 唯一服务名称;
Location 资源位置;
…
后面的字段是厂商自己定义的字段,因此厂商可根据需求扩展header字段。
编程实践
手机端进程需要:
新起一个线程管理SSDP消息的发送,称为搜索线程
新起一个线程监听响应,称为搜索响应监听线程
电视果进程需要:
新起一个线程监听搜索消息,称为搜索监听线程
收到搜索消息后新起一个线程发送响应消息,称为搜索响应线程
控制端监听设备的宣告消息
SSDP协议还规定了目标设备需要发送通知消息宣告在线, 如图4所示
192.168.1.112不定时发送多播消息,宣告设备在线,消息基于HTTP/1.1,携带了设备的一些信息,如设备名称,设备描述文件位置,设备标识等。192.168.1.102收到这个NOTIFY消息时,会获得192.168.1.112的信息,从而完成了设备发现过程。下面分析NOTIFY消息的报文格式。
在线消息
NOTIFY消息有header,无body。与M-SEARCH消息的响应消息相似。在Header里定义了设备相关的字段和值。
编程实践
手机端上:
新起一个线程监听在线消息,称为在线监听线程.
电视果上:
新起一个线程管理在线消息的发送,称为在线消息线程.
Bonjour协议
图1的tcpdump发现过程是192.168.1.100发现192.168.1.112的过程,即手机发现XXX的过程.
mDNS使用5353端口,mDNS协议定义了协议消息的基本格式和顺序:
224.0.0.251/5353是mDNS使用的多播消息地址;
xx:xx:xx:255/5353(如192.168.1.255:5353)是mDNS使用的广播消息地址。
为搜所设备,手机将query消息发到多播地址。而电视果将response消息同时发多播地址和广播地址。
为及时发现设备,XXX会每10s就发一次response消息,称为不请自来的消息,虽然并没有收到query消息也会发response消息。
在图1的发现过程看到192.168.1.102每次发6条消息,3条多播消息,3条广播消息。
手机上发的消息
图2的tcpdump手机上发的query消息.
这个query消息的Queries有3条记录:
_airplay._tcp.local
_raop._tcp.local
_airplay._tcp.local
消息从192.168.1.100:5353(手机上)发送到了224…0.0251:5353,该消息是一个多播消息。
1和3是一样的,因此这个query消息手机搜索支持_airplay._tcp和_raop._tcp的设备。
XXX上发的Query Response消息:
XXX上每一次发送的消息都包含6条没,3条广播到192.168.1.255:5353,另3条多播到224.0.0.251:5353,多播和广播的消息内容重复的,因此电视果总共发了3中query response消息,每一种消息包含一种服务记录:
wlan0.local: type A, class IN, cache flush, addr 192.168.1.112
_raop._tcp.local: type PTR, class IN, CCB8A813D00E@\347\224\265\350\247\206\346\236\234(103)._raop._tcp.local
_airplay._tcp.local: type PTR, class IN, \347\224\265\350\247\206\346\236\234(103)._airplay._tcp.local
这6条消息都是"不请自来"的消息,因为没有收到query消息而发的query response消息。
开源库JmDNS.
XXX上设备发现的过程:
首先probing消息连续发3次,间隔250ms;
然后announcing消息连续发2次,间隔1分钟;
在announced状态之后,Renewer每隔10s钟发送一次消息,每次都是6条,3条多播3条广播,类似DLNA的在线消息;
announced状态之后的消息在在图1发现过程中可以看到,但是probing和announcing的过程还没有找到tcpdump分析的方法。