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 相关文章推荐
java与javascript之间json格式数据互转介绍
Oct 29 Javascript
JS判断表单输入是否为空(示例代码)
Dec 23 Javascript
iframe里使用JavaScript控制主页转向的方法
Apr 03 Javascript
JavaScript的9种继承实现方式归纳
May 18 Javascript
Jquery中使用show()与hide()方法动画显示和隐藏图片
Oct 08 Javascript
动态的9*9乘法表效果的实现代码
May 16 Javascript
js实现按钮控制带有停顿效果的图片滚动
Aug 30 Javascript
微信小程序 跳转传递数据的实例
Jul 06 Javascript
phantomjs导出html到pdf的方法总结
Oct 19 Javascript
JS+HTML5 canvas绘制验证码示例
Dec 05 Javascript
微信小程序实现手势滑动卡片效果
Aug 26 Javascript
Ajax获取node服务器数据的完整步骤
Sep 20 Javascript
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 静态变量的初始化
2009/11/15 PHP
PHP加密解密类实例代码
2016/07/20 PHP
FormValid0.5版本发布,带ajax自定义验证例子
2007/08/17 Javascript
基于jquery实现的鼠标滑过按钮改变背景图片
2011/07/15 Javascript
JavaScript之编码规范 推荐
2012/05/23 Javascript
Lua表达式和控制结构学习笔记
2014/12/15 Javascript
jquery复选框多选赋值给文本框的方法
2015/01/27 Javascript
JS实现自动固定顶部的悬浮菜单栏效果
2015/09/16 Javascript
jQuery插件Timelinr 实现时间轴特效
2015/10/04 Javascript
JavaScript基础知识点归纳(推荐)
2016/07/09 Javascript
微信小程序 数据封装,参数传值等经验分享
2017/01/09 Javascript
谈谈Vue.js——vue-resource全攻略
2017/01/16 Javascript
Vue CLI3中使用compass normalize的方法
2019/05/30 Javascript
Vue路由的模块自动化与统一加载实现
2020/06/05 Javascript
Python基于Tkinter的HelloWorld入门实例
2015/06/17 Python
python取代netcat过程分析
2018/02/10 Python
基于tensorflow加载部分层的方法
2018/07/26 Python
python tornado微信开发入门代码
2018/08/24 Python
python 实现数字字符串左侧补零的方法
2018/12/04 Python
pyqt 多窗口之间的相互调用方法
2019/06/19 Python
Django单元测试工具test client使用详解
2019/08/02 Python
用python写测试数据文件过程解析
2019/09/25 Python
python 下划线的不同用法
2020/10/24 Python
matplotlib 画动态图以及plt.ion()和plt.ioff()的使用详解
2021/01/05 Python
HTML5 Video/Audio播放本地文件示例介绍
2013/11/18 HTML / CSS
优衣库美国官网:UNIQLO美国
2018/04/14 全球购物
欧姆龙医疗欧洲有限公司:Omron Healthcare Europe B.V
2020/06/13 全球购物
生物学学生自我评价
2014/01/17 职场文书
打架检讨书400字
2014/01/17 职场文书
厂办主管岗位职责范本
2014/02/28 职场文书
人力资源管理专业自荐信
2014/06/24 职场文书
2014党的群众路线教育实践活动总结材料
2014/10/31 职场文书
离婚协议书范文
2015/01/26 职场文书
党员转正申请报告
2015/05/15 职场文书
Java基于Dijkstra算法实现校园导游程序
2022/03/17 Java/Android
Nginx设置HTTPS的方法步骤 443证书配置方法
2022/03/21 Servers