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 相关文章推荐
Javascript下判断是否为闰年的Datetime包
Oct 26 Javascript
js中将具有数字属性名的对象转换为数组
Mar 06 Javascript
jQuery操作Select选择的Text和Value(获取/设置/添加/删除)
Mar 06 Javascript
JavaScript 模拟类机制及私有变量的方法及思路
Jul 10 Javascript
js操纵dom生成下拉列表框的方法
Feb 24 Javascript
PHPExcel中的一些常用方法汇总
Jan 23 Javascript
深入理解JavaScript中Ajax
Aug 02 Javascript
随机生成10个不重复的0-100的数字(实例讲解)
Aug 16 Javascript
nuxt+axios解决前后端分离SSR的示例代码
Oct 24 Javascript
微信小程序实现弹出菜单
Jul 19 Javascript
微信小程序支付前端源码
Aug 29 Javascript
JS实现可视化音频效果的实例代码
Jan 16 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/03/20 PHP
php笔记之:数据类型与常量的使用分析
2013/05/14 PHP
浅析PHP 按位与或 (^ 、&amp;)
2013/06/21 PHP
mongo Table类文件 获取MongoCursor(游标)的实现方法分析
2013/07/01 PHP
PHP SPL标准库之接口(Interface)详解
2015/05/11 PHP
php使用正则验证中文
2016/04/06 PHP
php+resumablejs实现的分块上传 断点续传功能示例
2017/04/18 PHP
MSN消息提示类
2006/09/05 Javascript
取得窗口大小 兼容所有浏览器的js代码
2011/08/09 Javascript
JQuery入门——用bind方法绑定事件处理函数应用介绍
2013/02/05 Javascript
JavaScript基础知识学习笔记
2014/12/02 Javascript
jquery实现可拖拽弹出层特效
2015/01/04 Javascript
jquery实现的仿天猫侧导航tab切换效果
2015/08/24 Javascript
VUE多层路由嵌套实现代码
2017/05/15 Javascript
vue中input的v-model清空操作
2019/09/06 Javascript
解决qrcode.js生成二维码时必须定义一个空div的问题
2020/07/09 Javascript
Vue跨域请求问题解决方案过程解析
2020/08/07 Javascript
Vue中使用JsonView来展示Json树的实例代码
2020/11/16 Javascript
[00:52]黑暗之门更新 新英雄孽主驾临DOTA2
2016/08/24 DOTA
[00:17]DOTA2荣耀之路5:It’s a disastah!
2018/05/28 DOTA
python实现去除下载电影和电视剧文件名中的多余字符的方法
2014/09/23 Python
Python中操作符重载用法分析
2016/04/29 Python
使用Python的Twisted框架构建非阻塞下载程序的实例教程
2016/05/25 Python
Python二叉树的定义及常用遍历算法分析
2017/11/24 Python
教你用 Python 实现微信跳一跳(Mac+iOS版)
2018/01/04 Python
Python3实现的字典遍历操作详解
2018/04/18 Python
Python Web编程之WSGI协议简介
2018/07/18 Python
python Web开发你要理解的WSGI &amp; uwsgi详解
2018/08/01 Python
python解压TAR文件至指定文件夹的实例
2019/06/10 Python
Python OpenCV中的resize()函数的使用
2019/06/20 Python
15个应该掌握的Jupyter Notebook使用技巧(小结)
2020/09/23 Python
米兰必去买手店排行榜首位:Antonioli
2016/09/11 全球购物
Manuka Doctor英国官网:真正的麦卢卡蜂蜜和护肤品
2018/10/26 全球购物
幼师专业求职推荐信
2013/11/08 职场文书
教师见习期自我鉴定
2014/04/28 职场文书
消防志愿者活动方案
2014/08/23 职场文书