node实现socket链接与GPRS进行通信的方法


Posted in Javascript onMay 20, 2019

业务背景

最近接到一个需求,在微信公众号界面设计一个独立界面,界面上有 A 电机进、A 电机退、B 电机进、B 电机退 4 个按钮,点击对应按钮,云平台发送不同的代码给电机本地的控制器,控制电机执行不同的动作,电机本地控制器具备GPRS网络功能。服务器与电机本地控制器(客户端)采用 TCP 协议连接,客户端发送心跳包给服务器保持长连接,客户端每次收到服务器下发的代码指令后作出回复主要的实现原理是前端访问后台的接口传输数据。后台采用用socket与GPRS模块进链接,暴露出一个IP+PORT给GPRS进行访问即可,实现逻辑比较简单。但是在开发中出现一下比较棘手问题,下面进行一一归纳。

技术栈

主要采用的技术栈前端部分采用vue和weUI,后台采用node的koa框架,前端页面是直接写在koa里面,由于页面比较简单,所以没有实现前后的分离。

实现过程

1、前端部分

node实现socket链接与GPRS进行通信的方法

前端部分实现主要是提供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)就可以发送绑定端口的数据。相对比较简单。可以参考一下nodejs.org/dist/latest… 看不懂英文可以找中文版的。

net的连接可以写在www文件或是app.js文件,看自己需求。在该项目中暴露出来接口127.0.0.1:3004,代码如下:

//socket
var net = require('net');
// 服务器IP
var 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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JQUERY THICKBOX弹出层插件
Aug 30 Javascript
Javascript 闭包引起的IE内存泄露分析
May 23 Javascript
js或者jquery判断图片是否加载完成实现代码
Mar 20 Javascript
Javascript学习笔记之 函数篇(一) : 函数声明和函数表达式
Jun 24 Javascript
jQuery实现彩带延伸效果的网页加载条loading动画
Oct 29 Javascript
AngularJS中$http服务常用的应用及参数
Aug 22 Javascript
浅谈js的异步执行
Oct 18 Javascript
js监听input输入框值的实时变化实例
Jan 26 Javascript
javascript移动端 电子书 翻页效果实现代码
Sep 07 Javascript
微信小程序自定义tabbar custom-tab-bar 6s出不来解决方案(cover-view不兼容)
Nov 01 Javascript
微信小程序多列表渲染数据开关互不影响的实现
Jun 05 Javascript
vue实现锚点定位功能
Jun 29 Vue.js
JS求1到任意数之间的所有质数的方法详解
May 20 #Javascript
react 中父组件与子组件双向绑定问题
May 20 #Javascript
vue element-ui之怎么封装一个自己的组件的详解
May 20 #Javascript
一文搞懂ES6中的Map和Set
May 20 #Javascript
详解vue 在移动端体验上的优化解决方案
May 20 #Javascript
vue-i18n结合Element-ui的配置方法
May 20 #Javascript
JS实现选项卡效果的代码实例
May 20 #Javascript
You might like
php 数组随机取值的简单实例
2016/05/23 PHP
laravel高级的Join语法详解以及使用Join多个条件
2019/10/16 PHP
jscript之Open an Excel Spreadsheet
2007/06/13 Javascript
javascript 写类方式之十
2009/07/05 Javascript
jquery 的 $(&quot;#id&quot;).html() 无内容的解决方法
2010/06/07 Javascript
Json对象替换字符串占位符实现代码
2010/11/17 Javascript
javascript hashtable 修正版 下载
2010/12/30 Javascript
JavaScript获取多个数组的交集简单实例
2013/11/11 Javascript
怎么选择Javascript框架(Javascript Framework)
2013/11/22 Javascript
原生JS封装ajax 传json,str,excel文件上传提交表单(推荐)
2016/06/21 Javascript
相册展示PhotoSwipe.js插件实现
2016/08/25 Javascript
js数组操作方法总结(必看篇)
2016/11/22 Javascript
深入理解JavaScript中的尾调用(Tail Call)
2017/02/07 Javascript
JavaScript实现打地鼠小游戏
2020/04/23 Javascript
Node.js实现发送邮件功能
2017/11/06 Javascript
JS中利用FileReader实现上传图片前本地预览功能
2018/03/02 Javascript
vue双向数据绑定知识点总结
2018/04/18 Javascript
浅谈一个webpack构建速度优化误区
2019/06/24 Javascript
vue中监听路由参数的变化及方法
2019/12/06 Javascript
如何使用 JavaScript 操作浏览器历史记录 API
2020/11/24 Javascript
python操作oracle的完整教程分享
2018/01/30 Python
python实现判断一个字符串是否是合法IP地址的示例
2018/06/04 Python
Django框架模板语言实例小结【变量,标签,过滤器,继承,html转义】
2019/05/23 Python
Python代码实现http/https代理服务器的脚本
2019/08/12 Python
使用python写的opencv实时监测和解析二维码和条形码
2019/08/14 Python
python中对_init_的理解及实例解析
2019/10/11 Python
Python+Opencv实现把图片、视频互转的示例
2020/12/17 Python
一款纯css3实现的漂亮的404页面的实例教程
2014/11/27 HTML / CSS
CSS3属性box-shadow使用指南
2014/12/09 HTML / CSS
.net软件工程师应聘上机试题
2015/03/10 面试题
如何写好建议书
2014/03/13 职场文书
团拜会策划方案
2014/06/07 职场文书
网络文明传播志愿者活动方案
2014/08/20 职场文书
《月光曲》教学反思
2016/02/16 职场文书
工作自我评价范文
2019/03/21 职场文书
mysq启动失败问题及场景分析
2021/07/15 MySQL