小程序开发必备的高级能力之四:mDNS
1、效果图
先瞅一眼效果图。
微信图片_20181217120824.png
2、释义
mDNS:即组播DNS(multicast DNS),使用5353端口,主要实现了在没有传统DNS服务器的情况下使局域网内的主机实现相互发现和通信。(--百度百科)
微信图片_20181217120820.png这段话什么意思呢?
其实是酱婶的,在客户端和服务端通信过程中(request,socket,websocket,ftp等),我们一般都需要知道对方的域名或者ip/port才能通信。
而在发送请求前,域名最终会经过一个叫DNS服务器的地方解析出相应的ip/port才能通信。
在局域网中,各个设备是没有域名的。此时我们只能通过ip/port来通信,但一般情况下各设备的ip是不固定的,它们是由DHCP分配的,在偶尔的掉线重连之后没准ip就变了,而且你也不知道要连接的设备的ip是多少。
基于此,mDNS登场了,它主要实现了设备间的互相发现。
emmmm,它没有通信功能。通信一般是通过socket来进行。
3、小程序中的mDNS
小程序中的mDNS主要有10个API
其中2个是主动事件,4个监听事件回调和4个取消监听事件回调
他们之间的关系是一一对应的。
而且,除了2个主动事件外,其他8个方法都是传1个回调方法过去
2个主动事件分别是:
1.开始搜寻局域网下的mDNS服务 wx.startLocalServiceDiscovery
2.停止搜索 mDNS 服务 wx.stopLocalSeviceDiscovery
4个监听事件回调分别是:
1.监听mDNS服务发现的事件 wx.onLocalServiceFound
2.监听mDSN服务解析失败的时间 wx.onLocalServiceResolveFail
3.监听mDNS服务离开的事件 wx.onLocalServiceLost
4.监听mDNS 服务停止搜索的事件 wx.onLocalServiceDiscoveryStop
4个取消监听事件回调分别是(目前这4个API无效?不知是否是我调用方式不对。但无所谓,这4个方法就算无效也没什么影响。)
1.取消监听mDNS 服务发现的事件 wx.offLocalServiceFound
2.取消监听mDNS 服务解析失败的事件 wx.offLocalServiceResolveFail
3.取消监听mDNS 服务离开的事件 wx.offLocalServiceLost
4.取消监听mDNS 服务停止搜索的事件 wx.offLocalServiceDiscoveryStop
4、实践
我们实现手动开启和关闭mDNS搜索,并在开启时实现mDNS监听事件的4个方法,在关闭时取消监听mDNS的4个方法。
wxml/wxss就不提,主要js实现如下。
/**
* 开始搜索
*/
startDiscovery:function(){
let that = this
serviceList = []
resolveFailList = []
wx.startLocalServiceDiscovery({
serviceType:'_http._tcp.',
success:function(res){
that.onLocalService()
},
fail:function(err){
console.log(err)
},
complete:function(){
console.log('complete')
}
})
},
/**
* stopDiscovery
*/
stopDiscovery:function(){
let that = this
wx.stopLocalServiceDiscovery({
success: function () {
that.showTips('停止搜索成功','success')
serviceList = []
resolveFailList = []
that.setData({
lists:[],
resolveFailList:[]
})
that.offLocalService()
},
fail: function () {
that.showTips('停止搜索失败,请重试!')
},
complete: function () {
console.log('stopDiscovery complete')
}
})
},
/**
* 提示方法
*/
showTips:function(title='出错啦',icon='none'){
wx.showToast({
title: title,
icon: icon,
duration:2000
})
},
/**
* 监听方法合集
*/
onLocalService:function(){
let that = this
// 监听服务发现事件
wx.onLocalServiceFound(function (obj) {
console.log(obj)
serviceList.push(obj)
that.setData({
lists: serviceList
})
})
// 监听服务解析失败事件
wx.onLocalServiceResolveFail(function (obj){
resolveFailList.push(obj)
that.setData({
resolveFailList: resolveFailList
})
})
// 监听服务离开
wx.onLocalServiceLost(function (obj){
that.showTips('有服务离开啦');
console.log(obj)
})
// 监听搜索停止
wx.onLocalServiceDiscoveryStop(function (obj){
console.log('监听到搜索停止事件')
})
},
/**
* offLocalService
*/
offLocalService: function () {
console.log('是否执行此部分数据')
// 取消监听服务发现事件
wx.offLocalServiceFound(function () {
console.log('取消监听服务发现事件 成功')
})
// 取消监听服务解析失败事件
wx.offLocalServiceResolveFail(function () {
console.log('取消监听 mDNS 服务解析失败的事件 成功')
})
// 取消监听服务离开
wx.offLocalServiceLost(function () {
console.log('取消监听服务离开事件 成功')
})
// 取消监听搜索停止
wx.offLocalServiceDiscoveryStop(function () {
console.log('取消监听 mDNS 服务停止搜索的事件 成功')
})
},
开始搜索 时正确,如下图。
微信图片_20181217120824.png
但是随后,每次停止搜索后再次开始搜索时,每个设备会被发现了2次。再停止搜索再开启搜索,会被发现3次。经定位,是取消监听的4个方法无效。(现在是2018-12-17 11:36),如下图。
微信图片_20181217120828.png
5、 最佳实践
其实,那4个取消监听的方法就算无效,对我们来说也不是很重要。
上面碰到的问题,无非是多次实现了监听事件而已。基于此,我们至少有2种解决方式。
1、使用statu来判断,不是第一次开启,就不再执行监听事件代码
2、在搜索之前就调用监听事件,开启搜索成功之后不再调用,这样子开启和关闭搜索功能,不和其他方法耦合。
于是,我们改进代码,使用第二种方法来解决这个问题。在onShow()中执行this.onLocalService(),并注释掉开启搜索成功回调里的代码即可。
最后把mdns这部分代码放到了github上。这里
6、其他注意事项
1、mdns只能真机调试
2、主动调用wx.stopLocalSeviceDiscovery()并不会触发wx.onLocalServiceDiscoveryStop事件,该事件在意外停止了搜索时才触发,例如手机屏幕关闭一段时间等。