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模拟select,jselect的方法实现
Nov 08 Javascript
关于JavaScript的变量的数据类型的判断方法
Aug 14 Javascript
js文件中直接alert()中文出来的是乱码的解决方法
Nov 01 Javascript
jQuery操作json常用方法示例
Jan 04 Javascript
详解vue事件对象、冒泡、阻止默认行为
Mar 20 Javascript
JS实现仿饿了么在浏览器标签页失去焦点时网页Title改变
Jun 01 Javascript
微信小程序url与token设置详解
Sep 26 Javascript
小程序实现展开/收起的效果示例
Sep 22 Javascript
JS实现倒计时图文效果
Nov 17 Javascript
vue使用echarts实现水平柱形图实例
Sep 09 Javascript
vue祖孙组件之间的数据传递案例
Dec 07 Vue.js
5种 JavaScript 方式实现数组扁平化
Oct 05 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下实现折线图效果的代码
2007/04/28 PHP
坏狼的PHP学习教程之第2天
2008/06/15 PHP
PHP5中虚函数的实现方法分享
2011/04/20 PHP
PHP运行出现Notice : Use of undefined constant 的完美解决方案分享
2012/03/05 PHP
Yii视图操作之自定义分页实现方法
2016/07/14 PHP
浅谈PHP接入(第三方登录)QQ登录 OAuth2.0 过程中遇到的坑
2017/10/13 PHP
PHP的PDO事务与自动提交
2019/01/24 PHP
php7连接MySQL实现简易查询程序的方法
2020/10/13 PHP
采用CSS和JS,刚好我最近有个站点要用到下拉菜单!
2006/06/26 Javascript
javascript 混合的构造函数和原型方式,动态原型方式
2009/12/07 Javascript
jQuery获取地址栏参数插件(模仿C#)
2010/10/26 Javascript
ASP.NET jQuery 实例7 通过jQuery来获取DropDownList的Text/Value属性值
2012/02/03 Javascript
javascript模拟select,jselect的方法实现
2012/11/08 Javascript
javascript中有趣的反柯里化深入分析
2012/12/05 Javascript
Express实现前端后端通信上传图片之存储数据库(mysql)傻瓜式教程(一)
2015/12/10 Javascript
在微信、支付宝、百度钱包实现点击返回按钮关闭当前页面和窗口的方法
2016/08/05 Javascript
原生js获取浏览器窗口及元素宽高常用方法集合
2017/01/18 Javascript
Three.js获取鼠标点击的三维坐标示例代码
2017/03/24 Javascript
微信小程序实现自定义加载图标功能
2018/07/19 Javascript
jQuery实现模拟搜索引擎的智能提示功能简单示例
2019/01/27 jQuery
使用taro开发微信小程序遇到的坑总结
2019/04/08 Javascript
vue实现将数据存入vuex中以及从vuex中取出数据
2019/11/08 Javascript
python实现通过shelve修改对象实例
2014/09/26 Python
Python中优化NumPy包使用性能的教程
2015/04/23 Python
Python中shutil模块的常用文件操作函数用法示例
2016/07/05 Python
python最长回文串算法
2018/06/04 Python
对python以16进制打印字节数组的方法详解
2019/01/24 Python
Nginx+Uwsgi+Django 项目部署到服务器的思路详解
2020/05/08 Python
基于python实现获取网页图片过程解析
2020/05/11 Python
python实现批处理文件
2020/07/28 Python
阿玛尼美妆俄罗斯官网:Giorgio Armani Beauty RU
2020/07/19 全球购物
质量月口号
2014/06/20 职场文书
我在伊朗长大观后感
2015/06/16 职场文书
企业内部管理控制:银行存款控制制度范本
2020/01/10 职场文书
Python3 如何开启自带http服务
2021/05/18 Python
Android实现获取短信验证码并自动填充
2023/05/21 Java/Android