最近在做一款物联网类型的小程序,要求通过小程序控制主板进行相关设置。
首先验证小程序是否支持UDP通信,查看官方api 支持的。

iOS 微信小程序由于不支持的分享类型_UDP

官方api访问地址:UDPSocket | 微信开放文档

根据需求,直接开始demo 构建。

没得说,先创建对象,直接上代码


if(this.UDPSocket == null || this.UDPSocket == undefined || this.UDPSocket == ''){    this.UDPSocket = wx.createUDPSocket(); } if(this.UDPSocket === null){    wx.showModal({      title: '温馨提示',        content: '尊敬的用户您好,您当前设备版本暂不支持UDP通信功能,请升级后再来!',        showCancel:false,        confirmText:'确定'    })    return }

上面多了一个校验,适配过低版本校验一下,当然了,不要也没问题。

注意:这里虽然走的是局域网通信,但是也是可以添加网络校验的,至于校验方法,官方给的有api这里就不在说了,大家根据需求随意添加。

创建好对象,下一部,绑定通信端口,至于为什么,这就需要您去查询什么是UDP通信了,UDP通信的方式。

不说废话,上代码

let port = this.UDPSocket.bind()

这里可以设置指定的端口,使用方法bind(port)

看官方的描述和代码

iOS 微信小程序由于不支持的分享类型_udp_02

bind()方法我们可以不传值,默认系统会给你随机分配一个端口号。如果绑定了,方法本身会给你返回一个绑定成功的端口。

注意了:这里的绑定一个指定端口的一个。很关键,如果您使用指定端口,这里需要注意。

我在这里也曾遇到过问题。我们后面再来说明。继续我们的流程。

绑定端口后,开始设置监听


this.UDPSocket.onListening(res=>{
      console.log('udp open',res)
    })
this.UDPSocket.onMessage(res=>{
      //处理接收到的数据
     if(res.remoteInfo.size > 0){
        // console.log('onUdpMessage() 接收数据 ' + res.remoteInfo.size + ' 字节:' + JSON.stringify(res, null, '\t'))
        // 将 ArrayBuffer类型的res.message取出来
        let unit8Arr = new Uint8Array(res.message)
        let encodedString = String.fromCharCode.apply(null, unit8Arr)
        let decodedString = decodeURIComponent(escape((encodedString)))//没有这一步中文会乱码
        console.log('UDP Received message',decodedString)
        // 将 ArrayBuffer类型的res.message取出来
        that.dealReceivedMsg(decodedString)
      }else{
        failure('接收到的信息为空!')
      }
    })


onListening() 方法,官方的说明是:监听开始监听数据包消息的事件

实际运行结果,这个方法要写,但是参数function 可以忽略,基本监听不到数据。

onMessage(function listener) 监听UDP收到的消息,不过要注意,这里返回的信息message 类型是ArrayBuffer。需要通过转换才能直接使用。转换方法,我是这样来写的,大家可以参考下。


let unit8Arr = new Uint8Array(res.message)
let encodedString = String.fromCharCode.apply(null, unit8Arr)
let decodedString = decodeURIComponent(escape((encodedString)))


最后我们再监听一下异常信息onError (),这里都不想碰到!


this.UDPSocket.onError(res=>{
      console.error('UDP error',res.errMsg)
    })


剩下最后一个关键了,UDP发消息


this.UDPSocket.send({
   address:'192.168.1.1',
   port:2023,
   setBroadcast:true,
   message:msg
 })


send方法,参数介绍我们就看官方的api就可以了,我就偷懒了,截图奉上

iOS 微信小程序由于不支持的分享类型_UDP_03

除了必传参数,其他参数,大家根据需求自定义。

如果可以,最好再不使用的时候,调一下close 方法。官方的描述是这样的

关闭 UDP Socket 实例,相当于销毁。 在关闭之后,UDP Socket 实例不能再发送消息,每次调用 UDPSocket.send 将会触发错误事件,并且 message 事件回调函数也不会再也执行。在 UDPSocket 实例被创建后将被 Native 强引用,保证其不被 GC。在 UDPSocket.close 后将解除对其的强引用,让 UDPSocket 实例遵从 GC。

注意:这里调用后,是相当于销毁不等于已经销毁了。所以要特别注意。!!!

后面分享下我遇到的问题,以及解决方法,希望可以帮助到大家。

在最后我再分享下我遇到的问题以及解决方法,希望对大家有用!!

===继续==========

到这里我们就完成了。测试下结果看看效果如何。

iOS 微信小程序由于不支持的分享类型_经验分享_04

一切都没问题。

到这里就结束了!!!

-------------- wait for a moment -----------

我的问题:------------- start ----------------

创建后使用bind(2023),绑定了接收消息的指定端口。按照其他项目的经验,这个是没错的。我在开发和预览模式下都没问题,真机模式下,Android 成功率98%,ios 却不行了成功率只有不到5%。

报异常信息:udp can not find client

port is in using 遇到这个问题,我们打印的bind的端口返回是0。意思就是端口被占用了,我们即使使用close 也不行,要等待系统自己gc。

上面的两个问题,遇到任何一个,你的udp 就无法使用。

所以如果要使用bind(端口)来执行,那么,调试的时候,注意不要频繁启动。如果你的项目中UDP通信使用比较频繁或者使用概率很大。不是临时的,只在某个page使用的时候。建议使用随机端口。因为经过实际测试,小程序上面,你是否绑定指定端口,都会收到UDP消息。是不是豁然开朗了!

想当初遇到问题,找了好多资料,没有找到问题,继续分析官网的api。最终解决问题。所以这里发个文,遇到同样的可以参考下,希望能帮助大家!

--------------------------- end --------------