1、效果圖
先瞅一眼效果圖涉波。
2、釋義
mDNS:即組播DNS(multicast DNS)炭序,使用5353端口啤覆,主要實(shí)現(xiàn)了在沒(méi)有傳統(tǒng)DNS服務(wù)器的情況下使局域網(wǎng)內(nèi)的主機(jī)實(shí)現(xiàn)相互發(fā)現(xiàn)和通信。(--百度百科)
這段話什么意思呢惭聂?
其實(shí)是醬嬸的城侧,在客戶端和服務(wù)端通信過(guò)程中(request,socket,websocket,ftp等),我們一般都需要知道對(duì)方的域名或者ip/port才能通信彼妻。
而在發(fā)送請(qǐng)求前嫌佑,域名最終會(huì)經(jīng)過(guò)一個(gè)叫DNS服務(wù)器的地方解析出相應(yīng)的ip/port才能通信。
在局域網(wǎng)中侨歉,各個(gè)設(shè)備是沒(méi)有域名的屋摇。此時(shí)我們只能通過(guò)ip/port來(lái)通信,但一般情況下各設(shè)備的ip是不固定的幽邓,它們是由DHCP分配的炮温,在偶爾的掉線重連之后沒(méi)準(zhǔn)ip就變了,而且你也不知道要連接的設(shè)備的ip是多少牵舵。
基于此柒啤,mDNS登場(chǎng)了,它主要實(shí)現(xiàn)了設(shè)備間的互相發(fā)現(xiàn)畸颅。
emmmm担巩,它沒(méi)有通信功能。通信一般是通過(guò)socket來(lái)進(jìn)行没炒。
3涛癌、小程序中的mDNS
小程序中的mDNS主要有10個(gè)API
其中2個(gè)是主動(dòng)事件,4個(gè)監(jiān)聽(tīng)事件回調(diào)和4個(gè)取消監(jiān)聽(tīng)事件回調(diào)
他們之間的關(guān)系是一一對(duì)應(yīng)的。
而且拳话,除了2個(gè)主動(dòng)事件外先匪,其他8個(gè)方法都是傳1個(gè)回調(diào)方法過(guò)去
2個(gè)主動(dòng)事件分別是:
1.開(kāi)始搜尋局域網(wǎng)下的mDNS服務(wù) wx.startLocalServiceDiscovery
2.停止搜索 mDNS 服務(wù) wx.stopLocalSeviceDiscovery
4個(gè)監(jiān)聽(tīng)事件回調(diào)分別是:
1.監(jiān)聽(tīng)mDNS服務(wù)發(fā)現(xiàn)的事件 wx.onLocalServiceFound
2.監(jiān)聽(tīng)mDSN服務(wù)解析失敗的時(shí)間 wx.onLocalServiceResolveFail
3.監(jiān)聽(tīng)mDNS服務(wù)離開(kāi)的事件 wx.onLocalServiceLost
4.監(jiān)聽(tīng)mDNS 服務(wù)停止搜索的事件 wx.onLocalServiceDiscoveryStop
4個(gè)取消監(jiān)聽(tīng)事件回調(diào)分別是(目前這4個(gè)API無(wú)效?不知是否是我調(diào)用方式不對(duì)弃衍。但無(wú)所謂呀非,這4個(gè)方法就算無(wú)效也沒(méi)什么影響。)
1.取消監(jiān)聽(tīng)mDNS 服務(wù)發(fā)現(xiàn)的事件 wx.offLocalServiceFound
2.取消監(jiān)聽(tīng)mDNS 服務(wù)解析失敗的事件 wx.offLocalServiceResolveFail
3.取消監(jiān)聽(tīng)mDNS 服務(wù)離開(kāi)的事件 wx.offLocalServiceLost
4.取消監(jiān)聽(tīng)mDNS 服務(wù)停止搜索的事件 wx.offLocalServiceDiscoveryStop
4镜盯、實(shí)踐
我們實(shí)現(xiàn)手動(dòng)開(kāi)啟和關(guān)閉mDNS搜索姜钳,并在開(kāi)啟時(shí)實(shí)現(xiàn)mDNS監(jiān)聽(tīng)事件的4個(gè)方法,在關(guān)閉時(shí)取消監(jiān)聽(tīng)mDNS的4個(gè)方法形耗。
wxml/wxss就不提哥桥,主要js實(shí)現(xiàn)如下。
/**
* 開(kāi)始搜索
*/
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('停止搜索失敗激涤,請(qǐng)重試拟糕!')
},
complete: function () {
console.log('stopDiscovery complete')
}
})
},
/**
* 提示方法
*/
showTips:function(title='出錯(cuò)啦',icon='none'){
wx.showToast({
title: title,
icon: icon,
duration:2000
})
},
/**
* 監(jiān)聽(tīng)方法合集
*/
onLocalService:function(){
let that = this
// 監(jiān)聽(tīng)服務(wù)發(fā)現(xiàn)事件
wx.onLocalServiceFound(function (obj) {
console.log(obj)
serviceList.push(obj)
that.setData({
lists: serviceList
})
})
// 監(jiān)聽(tīng)服務(wù)解析失敗事件
wx.onLocalServiceResolveFail(function (obj){
resolveFailList.push(obj)
that.setData({
resolveFailList: resolveFailList
})
})
// 監(jiān)聽(tīng)服務(wù)離開(kāi)
wx.onLocalServiceLost(function (obj){
that.showTips('有服務(wù)離開(kāi)啦');
console.log(obj)
})
// 監(jiān)聽(tīng)搜索停止
wx.onLocalServiceDiscoveryStop(function (obj){
console.log('監(jiān)聽(tīng)到搜索停止事件')
})
},
/**
* offLocalService
*/
offLocalService: function () {
console.log('是否執(zhí)行此部分?jǐn)?shù)據(jù)')
// 取消監(jiān)聽(tīng)服務(wù)發(fā)現(xiàn)事件
wx.offLocalServiceFound(function () {
console.log('取消監(jiān)聽(tīng)服務(wù)發(fā)現(xiàn)事件 成功')
})
// 取消監(jiān)聽(tīng)服務(wù)解析失敗事件
wx.offLocalServiceResolveFail(function () {
console.log('取消監(jiān)聽(tīng) mDNS 服務(wù)解析失敗的事件 成功')
})
// 取消監(jiān)聽(tīng)服務(wù)離開(kāi)
wx.offLocalServiceLost(function () {
console.log('取消監(jiān)聽(tīng)服務(wù)離開(kāi)事件 成功')
})
// 取消監(jiān)聽(tīng)搜索停止
wx.offLocalServiceDiscoveryStop(function () {
console.log('取消監(jiān)聽(tīng) mDNS 服務(wù)停止搜索的事件 成功')
})
},
開(kāi)始搜索 時(shí)正確,如下圖倦踢。
但是隨后送滞,每次停止搜索后再次開(kāi)始搜索時(shí),每個(gè)設(shè)備會(huì)被發(fā)現(xiàn)了2次辱挥。再停止搜索再開(kāi)啟搜索犁嗅,會(huì)被發(fā)現(xiàn)3次。經(jīng)定位晤碘,是取消監(jiān)聽(tīng)的4個(gè)方法無(wú)效褂微。(現(xiàn)在是2018-12-17 11:36),如下圖园爷。
5宠蚂、 最佳實(shí)踐
其實(shí),那4個(gè)取消監(jiān)聽(tīng)的方法就算無(wú)效童社,對(duì)我們來(lái)說(shuō)也不是很重要求厕。
上面碰到的問(wèn)題,無(wú)非是多次實(shí)現(xiàn)了監(jiān)聽(tīng)事件而已扰楼⊙窖ⅲ基于此,我們至少有2種解決方式弦赖。
1项栏、使用statu來(lái)判斷,不是第一次開(kāi)啟腾节,就不再執(zhí)行監(jiān)聽(tīng)事件代碼
2忘嫉、在搜索之前就調(diào)用監(jiān)聽(tīng)事件,開(kāi)啟搜索成功之后不再調(diào)用案腺,這樣子開(kāi)啟和關(guān)閉搜索功能庆冕,不和其他方法耦合。
于是劈榨,我們改進(jìn)代碼访递,使用第二種方法來(lái)解決這個(gè)問(wèn)題。在onShow()中執(zhí)行this.onLocalService()同辣,并注釋掉開(kāi)啟搜索成功回調(diào)里的代碼即可拷姿。
最后把mdns這部分代碼放到了github上。這里
6旱函、其他注意事項(xiàng)
1响巢、mdns只能真機(jī)調(diào)試
2、主動(dòng)調(diào)用wx.stopLocalSeviceDiscovery()并不會(huì)觸發(fā)wx.onLocalServiceDiscoveryStop事件棒妨,該事件在意外停止了搜索時(shí)才觸發(fā)踪古,例如手機(jī)屏幕關(guān)閉一段時(shí)間等。