想要在同一个局域网内,发现其他设备。有如下的几种方案。
-
应用起来之后,请求同一个地址,构建同一个组。每个应用就是这个组的成员。每个成员之间相互知道。
这样的方案,缺点是需要有一个中心,用来管理这些成员 -
在同一局域网内,相互之间广播。广播内容,可以是自己的ip和对应服务的端口号,以及需要携带的信息。
这样的方案,缺点就是广播可能会带来大量的网络阻塞。 -
在同一局域网内,使用多播。android 内置有mDNS服务,和客户端,它就是使用的多播方式。可以将自身被
其他设备发现,也可以发现其他设备。
在介绍mDns的使用之前。先来说说广播和多播的原理。
广播原理简述
IPV4 将子网的最后一位地址。作为广播地址。比如192.168.1.0/24子网中,广播地址为192.168.1.255.
所有数据包的目的地址为192.168.1.255时。
路由设备会将这个数据包,发往该子网内的所有设备。
除了192.168.1.255外,另外一个地址为255.255.255.255是全局广播地址。但是路由器并不会将它转发到其他网络中,它只会转发到本网络中。因此效果和192.168.1.255一样。
多播原理简述
在上面广播会转发给本网络的所有设备不同。多播只会转发给特定的设备。那些设备是特定设备呢?基本步骤如下:
- 需要接收多播数据包的设备,使用IGMP协议(这是一个网络层协议)将自己的IP地址,报告给路由器,表示自己要接收某个多播IP的数据包
- 路由器在接收到第一步的IP地址之后,就保存下来。如果有某个设备发了一个多播的数据包给路由器,那么路由器就将这个数据包,转发给这个多播组内的所有成员。
- 正如广播地址一样,多播也是有地址划分的,他是IPV4D类地址,范围是224.0.0.0到239.255.255.255。
- 多播地址常常是固定的,比如即将介绍的mDNS的多播地址为224.0.0.251
android的mDNS
android使用NsdManager进行mDns的注册和发现操作。使用步骤如下
- 获取NsdManager.
val nsdManager: NsdManager = getSystemService(Context.NSD_SERVICE) as NsdManager
- 发现其他设备,并解析
//其中的listener接口,请参考android api,相对简单
nsdManager.discoverServices("_http._tcp.", NsdManager.PROTOCOL_DNS_SD, discoveryListener)
nsdManager.resolveService(serviceInfo, resolveListener)
注意,在dicoverServices的listener中,发现服务之后,会返回一个NsdServiceInfo的消息。需要使用resolverService接口才能够正确的解析NsdServiceInfo中的消息
- 注册服务,让自身可被其他设备发现
//serviceName 是可以被发现的服务名字
//serviceType 是服务的类型,简单说一下有哪些服务类型。有:_http._tcp.表示http服务
// _ipp._tcp表示打印机服务
// _rfp._tcp表示远程Framebuffer,如远程桌面(android不支持)
// _workstation._tcp表示路由器,(android不支持)
var serviceInfo = NsdServiceInfo()
serviceInfo.serviceName = "wanbiao's android platform"
serviceInfo.serviceType = "_http._tcp."
serviceInfo.port = 1234
serviceInfo.setAttribute("hostname","wanbiao")
(getSystemService(Context.NSD_SERVICE) as NsdManager).registerService(
serviceInfo,
NsdManager.PROTOCOL_DNS_SD,
registrationListener
)
如何测试
可以使用linux设备的mDns进行快速的测试
本机使用ubuntu 进行测试,ubuntu可以使用avahi开源工具进行测试。
安装命令
sudo apt-get install avahi-daemon
启动服务
sudo service avahi-daemon start
使用图形工具,进行mDns的查看
安装图形工具
sudo apt-get install avahi-discover
打开并查看
avahi-dicover
使用命令行测试
#在我本机例子中,我的mDns的本地域名为Android.local
ping Android.local
可见在linux系统中,还可以通过本地域名进行解析。但是Android中无法这样使用。
只能通过IP进行通信。
本笔记完