業務背景
最近接到一個需求,在微信公眾號界面設計一個獨立界面,界面上有 A 電機進、A 電機退、B 電機進、B 電機退 4 個按鈕,點擊對應按鈕,云平臺發送不同的代碼給電機本地的控制器,控制電機執行不同的動作,電機本地控制器具備GPRS網絡功能。服務器與電機本地控制器(客戶端)采用 TCP 協議連接,客戶端發送心跳包給服務器保持長連接,客戶端每次收到服務器下發的代碼指令后作出回復主要的實現原理是前端訪問后臺的接口傳輸數據。后臺采用用socket與GPRS模塊進鏈接,暴露出一個IP+PORT給GPRS進行訪問即可,實現邏輯比較簡單。但是在開發中出現一下比較棘手問題,下面進行一一歸納。
技術棧
主要采用的技術棧前端部分采用vue和weUI,后臺采用node的koa框架,前端頁面是直接寫在koa里面,由于頁面比較簡單,所以沒有實現前后的分離。
實現過程
1、前端部分
前端部分實現主要是提供4個按鈕,向后臺接口請求對應的數據,例如:點擊A點擊前進,就向后臺請求http://XXXX:4000/djxt/move接口并傳輸數據,可以下載完整項目運行后,通過127.0.0.1:3002/djxt進行訪問,頁面html代碼主要部分如下:
<div class="wrap"> <button @click="goA('A1')" class="weui-btn" v-bind:class="{ 'weui-btn_loading': btnStatus.cur == 'A1'&&btnStatus.status==0, 'weui-btn_primary': btnStatus.cur == 'A1'&&btnStatus.status==1, 'weui-btn_plain-primary': btnStatus.cur != 'A1' }">A 前進<i v-show="btnStatus.cur == 'A1'&&btnStatus.status==0" class="weui-loading"></i></button> <button @click="backA('A0')" class="weui-btn" v-bind:class="{ 'weui-btn_loading': btnStatus.cur == 'A0'&&btnStatus.status==0, 'weui-btn_primary': btnStatus.cur == 'A0'&&btnStatus.status==1, 'weui-btn_plain-default': btnStatus.cur != 'A0' }">A 后退<i v-show="btnStatus.cur == 'A0'&&btnStatus.status==0" class="weui-loading"></i></button> <button @click="goB('B1')" class="weui-btn" v-bind:class="{ 'weui-btn_loading': btnStatus.cur == 'B1'&&btnStatus.status==0, 'weui-btn_primary': btnStatus.cur == 'B1'&&btnStatus.status==1, 'weui-btn_plain-primary': btnStatus.cur != 'B1' }">B 前進<i v-show="btnStatus.cur == 'B1'&&btnStatus.status==0" class="weui-loading"></i></button> <button @click="backB('B0')" class="weui-btn" v-bind:class="{ 'weui-btn_loading': btnStatus.cur == 'B0'&&btnStatus.status==0, 'weui-btn_primary': btnStatus.cur == 'B0'&&btnStatus.status==1, 'weui-btn_plain-default': btnStatus.cur != 'B0' }">B 后退<i v-show="btnStatus.cur == 'B0'&&btnStatus.status==0" class="weui-loading"></i></button> </div>
發送數據給后臺部分代碼如下:
// A 前進 goA (id){ axios.post('/djxt/move', { id }) .then( (response)=> { console.log(response); if( response.data.success ){ this.alertDialog.content = '操作成功'; this.alertDialog.status = true; }else{ this.alertDialog.content = '操作失敗了'; this.alertDialog.status = true; } }) .catch( (error)=> { console.log(error); this.alertDialog.content = '操作失敗了'; this.alertDialog.status = true; }); }
2、后臺實現
由于用的是node技術棧,當初使用的是scoket.io來進行scoket鏈接的,但是在后面的開發中發現該方法需要有一個事件去觸發提交數據,在客戶端也需要有事件進行監聽,不適合在與GPRS進行通信,最后無奈的放棄了。后面采用了node的NET模塊進行通信,該模塊只要調用write(data)就可以發送綁定端口的數據。相對比較簡單??梢詤⒖家幌耼odejs.org/dist/latest… 看不懂英文可以找中文版的。
net的連接可以寫在www文件或是app.js文件,看自己需求。在該項目中暴露出來接口127.0.0.1:3004,代碼如下:
//socketvar net = require('net');// 服務器IPvar HOST = '127.0.0.1';// 端口號var PORT = 3004;// 創建一個TCP服務器實例,調用listen函數開始監聽指定端口// 傳入net.createServer()的回調函數將作為”connection“事件的處理函數// 在每一個“connection”事件中,該回調函數接收到的socket對象是唯一的net.createServer(function(sock) {// 全局sock,可以在其他地方調用global.sock = sock// 獲得了一個socket連接,將客戶端輸出來console.log('CONNECTED: ' + sock.remoteAddress + ':' + sock.remotePort);// 為這個socket實例添加一個"data"事件處理函數,接收客戶端數據sock.on('data', function(data) { console.log('DATA ' + sock.remoteAddress + ': ' + data); // 回發該數據,客戶端將收到來自服務端的數據,實現ECHO服務器 // sock.write('' + data );});// 為這個socket實例添加一個"close"事件處理函數sock.on('close', function(data) { console.log('CLOSED: ' + sock.remoteAddress + ' ' + sock.remotePort);});}).listen(PORT, HOST);
代碼中的HOST 是你需要暴露給GPRS模塊的ip,PORT是端口。net.createServer創建服務后,它回調里面的sock可以用來做一些監聽,例如客戶端返回數據sock.on('data', function(data) {})。在開發過程中遇到一個問題就是HOST在本地是用127.0.0.1是可以進行訪問的,但是到了云服務后,會出現端口訪問不了。解決辦法是把HOST改為你自己服務器的內網ip即可進行訪問。global.sock = sock這個主要是暴露全局的sock,可以在其他需要地方進行調用,切記要暴露出去。
服務端處理前端發送過來的數據,發送到GPRS模塊。該項目中前端訪問的路由為/move,進入這個路由后進行判斷,再把值轉發給GPRS,這里關鍵點是利用全局的Sock的sock.write()來發送到客戶端。代碼如下
//前端接口router.post('/move', async (ctx, next) => { let params = ctx.request.body; // console.log('ctx.state: ', global.sock) // console.log('ctx.state2222: ', sock) console.log('前端接口: ', params) if( !sock ){ ctx.body = { data: params, success: false, msg: 'socket不存在' } }else{ sock.write( params.id ); ctx.body = { data: params, success: true, msg: '' } }})
完整的代碼可參考github。https://github.com/bayi-lzp/node_djxt_socket
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。
新聞熱點
疑難解答