前言 UDP通信分为单播 广播 组播,基础库2.7.0之后,小程序开始支持UDP通信,目前小程序只支持单播。 小程序API 小程序UDP通信这一块可以说是很简单了就一个UDPSocket实例。然后bind()方法绑定端口,send()方法发送数据,close()方法关闭通信,onMessage()方法监听消息等等,具体可以去看文档 相关技术难点 使用UDP通信时,如果是用于局域网内数据传输,这里有个难点就是,不知道本机及对应要通信设备在当前局域网内的ip及绑定的端口。如果是用于和服务器之间的数据传输的话,没想出具体应用场景... 通信效果展示 由于没有2台手机,所以用node.js代码充当了其中一台客户端,先看看客户端间通信截图。 client1.png client2.png Node.js端代码 通过dgram框架进行操作,这里由于演示,所以每次都简单地返回相同的数据。 const dgram = require(\'dgram\'); const server = dgram.createSocket(\'udp4\'); server.on(\'close\',()=>{ console.log(\'socket已关闭\'); }); server.on(\'error\',(err)=>{ console.log(err); }); server.on(\'listening\',()=>{ console.log(\'socket正在监听中...\'); }); server.on(\'message\',(msg,rinfo)=>{ console.log(`receive message from ${rinfo.address}:${rinfo.port}`); console.log(`message=${msg}`) server.send(\'收到你的信息了\',rinfo.port,rinfo.address) }); server.bind(\'8060\'); 小程序端代码 代码比较简单,唯一需要注意的是,接收到udp消息时,数据是ArrayBuffter格式的,需要转成string显示。(这部分代码在js代码最下方) // js代码 // pages/welcome/welcome.js let util = require(\'../../utils/util.js\') Page({ udpSocket:null, /** * 页面的初始数据 */ data: { messageList:[] }, mydata:{ message:\'\', remoteUrl: { ip: \'\', port: -1 }, isSend:false }, addMessage(event){ console.log(event) this.mydata.message = event.detail.value }, sendMessage(){ if (this.mydata.isSend){ return ; } this.mydata.isSend = true let ip = this.mydata.remoteUrl.ip let port = this.mydata.remoteUrl.port let message = this.mydata.message if(message.trim() === \'\'){ wx.showToast({ title: \'请输入内容\', }) return ; } udpSocket.send({ address: ip, port: port, message: message }) this.mydata.isSend = false let list = this.data.messageList let obj = { text: message, from : 2 } list.push(obj) this.setData({ messageList : list }) }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { this.initUdpSocket() }, initUdpSocket(){ udpSocket = wx.createUDPSocket(); if(udpSocket === null){ console.log(\'暂不支持\') return ; } const locationPort = udpSocket.bind() this.setData({ \'locationUrl.port\': locationPort }) udpSocket.onListening(function(res){ console.log(\'监听中...\') console.log(res) }) let that = this udpSocket.onMessage(function (res) { console.log(res) let str = util.newAb2Str(res.message) console.log(\'str===\'+str) let list = that.data.messageList let obj = { text: str, from: 1 } list.push(obj) that.setData({ messageList: list }) }) }, /** * 输入ip/端口号 */ addIp: function(event){ this.mydata.remoteUrl.ip = event.detail.value }, addPort: function (event){ this.mydata.remoteUrl.port = event.detail.value }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { }, /** * 生命周期函数--监听页面显示 */ onShow: function () { } } // util.newAb2Str代码 function newAb2Str(arrayBuffer){ let unit8Arr = new Uint8Array(arrayBuffer); let encodedString = String.fromCharCode.apply(null, unit8Arr), decodedString = decodeURIComponent(escape((encodedString)));//没有这一步中文会乱码 return decodedString; } 相应的WXML和WXSS代码 <!-- wxml --> <!--pages/welcome/welcome.wxml--> <view> <view class=\'header\'> <view> <text>本机端口:{{locationUrl.port}}</text> </view> <view class=\'headerItem\'> <text>IP地址:</text> <input type=\'text\' bindinput=\'addIp\'></input> </view> <view class=\'headerItem\'> <text>端口:</text> <input type=\'number\' bindinput=\'addPort\'></input> </view> </view> <view class=\'content\'> <block wx:for="{{messageList}}" wx:key="{{index}}"> <view wx:if="{{item.from === 1}}" class=\'fromLeft\'> <text>{{item.text}}</text> </view> <view wx:else class=\'fromRight\'> <text>{{item.text}}</text> </view> </block> </view> <view class=\'footer\'> <input type=\'text\' bindinput=\'addMessage\'></input> <button bindtap=\'sendMessage\'>发送</button> </view> </view> // wxss /* pages/welcome/welcome.wxss */ .header{ padding: 20rpx; border-bottom: solid 1px #dfdfdf; } .headerItem{ display: flex; flex-direction: row; justify-content: flex-start; align-items: center; margin-top: 10rpx; height: 50rpx; } .headerItem > text{ color: #333; width: 150rpx; font-size: 30rpx; text-align: right; } .headerItem > input{ border: solid 1px #dfdfdf; } .content{ padding: 0 20rpx; } .content > view{ margin-top: 10rpx; display: flex; flex-direction: column; justify-content: flex-start; align-items: flex-start; } .content > .fromLeft > text{ padding: 10rpx; width: 690rpx; text-align: left; background-color: orangered; color: white; } .content > .fromRight > text{ padding: 10rpx; width: 690rpx; text-align: right; background-color: #dfdfdf; color: white; } .footer{ display: flex; flex-direction: row; justify-content: flex-start; align-items: center; padding: 0 20rpx; margin-top: 20rpx; } .footer > input{ border: solid 2rpx #dfdfdf; border-radius: 4rpx; width: 500rpx; height: 70rpx; line-height: 70rpx; margin-right: 10rpx; } .footer > button{ width: 200rpx; height: 70rpx; line-height: 70rpx; }