前言 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; }