微信小程序使用websocket通讯的demo,含前后端代码,亲测可用


Posted in Javascript onMay 22, 2019

0、概述websocket

(1) 个人总结:后台设置了websocket地址,服务器开启后等待有人去连接它。 一个客户端一打开就去连接websocket地址,同时传递某些识别参数。这样一来后台和客户端连接成功了,然后后台就可以发消息给客户端了,(客户端也可以再回话给后台)。

(2) socket叫套接字,应用程序用socket向网络发出请求或者应答网络请求。

(3) 官方解释的socket 建立连接四步骤:

服务器端开启socket,然后accep方法处于监听状态,等待客户端的连接。

 客户端开启,指定服务器名称和端口号来请求连接服务器端的socket。
 服务器端收到客户端连接请求,返回连接确认。在服务器端,accept() 方法返回服务器上一个新的 socket 引用,该 socket 连接到客户端的 socket。
 客户端收到连接确认,两个人就连接好了,双方开始通讯

(4)注意:

客户端的输出流连接到服务器端的输入流,而客户端的输入流连接到服务器端的输出流。
TCP 是一个双向的通信协议,因此数据可以通过两个数据流在同一时间发送.

1、app.js写法

在app.js下添加三个函数openSocket(), closeSocket(),sendMessage(),在app初始化的onLunch函数里面调用openSocket(),这样子用户一进入小程序就会自动连接websocket

App({
  globalData: {
  socketStatus: 'closed',
  },
 onLaunch: function() { 
  var that = this;
  if (that.globalData.socketStatus === 'closed') {
    that.openSocket();
  }
 }
 openSocket() {
  //打开时的动作
  wx.onSocketOpen(() => {
   console.log('WebSocket 已连接')
   this.globalData.socketStatus = 'connected';
   this.sendMessage();
  })
  //断开时的动作
  wx.onSocketClose(() => {
   console.log('WebSocket 已断开')
   this.globalData.socketStatus = 'closed'
  })
  //报错时的动作
  wx.onSocketError(error => {
   console.error('socket error:', error)
  })
  // 监听服务器推送的消息
  wx.onSocketMessage(message => {
   //把JSONStr转为JSON
   message = message.data.replace(" ", "");
   if (typeof message != 'object') {
   message = message.replace(/\ufeff/g, ""); //重点
   var jj = JSON.parse(message);
   message = jj;
   }
   console.log("【websocket监听到消息】内容如下:");
   console.log(message);
  })
  // 打开信道
  wx.connectSocket({
   url: "ws://" + "localhost" + ":8888",
  })
  },
 //关闭信道
  closeSocket() {
  if (this.globalData.socketStatus === 'connected') {
   wx.closeSocket({
   success: () => {
    this.globalData.socketStatus = 'closed'
   }
   })
  }
  },
  //发送消息函数
  sendMessage() {
  if (this.globalData.socketStatus === 'connected') {
  //自定义的发给后台识别的参数 ,我这里发送的是name
   wx.sendSocketMessage({
   data: "{\"name\":\"" + wx.getStorageSync('openid') + "\"}" 
   })
  }
  },
})

2、后台写法

主要有两个类,一个是websocket启动监听交互类,一个是存储当前所有已经连接好的用户池以及对这些用户的操作封装类
 然后在项目启动类里面调用websocke启动监听交互类的启动方法。(如果是springboot项目,就直接在主类中调用)

(1)导入包

<dependency>
 <groupId>org.java-websocket</groupId>
 <artifactId>Java-WebSocket</artifactId>
 <version>1.3.0</version>
</dependency>
  

(2)启动websocket的方法,放在启动类里面   

/**
  * 启动websocket
  */
 public void startWebsocketInstantMsg() {
  WebSocketImpl.DEBUG = false;
  MyWebScoket s;
  s = new MyWebScoket(8888);
  s.start();
  System.out.println("websocket启动成功");
 }

(3)websocket监听交互类如下

 该类涉及的监听方法有:监听用户连入;监听用户断开;监听消息发过来;监听有错误等

import com.alibaba.fastjson.JSONObject;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Map;
public class MyWebScoket extends WebSocketServer {
 public MyWebScoket() throws UnknownHostException {
  super();
 }
 public MyWebScoket(int port) {
  super(new InetSocketAddress(port));
 }
 public MyWebScoket(InetSocketAddress address) {
  super(address);
 }
 @Override
 public void onOpen(WebSocket conn, ClientHandshake handshake) {
  // ws连接的时候触发的代码,onOpen中我们不做任何操作
 }
 @Override
 public void onClose(WebSocket conn, int code, String reason, boolean remote) {
  //断开连接时候触发代码
  userLeave(conn);
  System.out.println(reason);
 }
 @Override
 public void onMessage(WebSocket conn, String message) {
  //有用户连接进来
  Map<String, String> obj = (Map<String,String>) JSONObject.parse(message);
  System.out.println(message);
  String username = obj.get("name");
  userJoin(conn, username);
 }
 @Override
 public void onError(WebSocket conn, Exception ex) {
  //错误时候触发的代码
  System.out.println("on error");
  ex.printStackTrace();
 }
 /**
  * 去除掉失效的websocket链接
  */
 private void userLeave(WebSocket conn){
  WsPool.removeUser(conn);
 }
 /**
  * 将websocket加入用户池
  * @param conn
  * @param userName
  */
 private void userJoin(WebSocket conn,String userName){
  WsPool.addUser(userName, conn);
 }
}

(4)用户池类如下

 该类包含的方法有:从池中移除或添加用户;获取当前在线的所有用户;通过参数"name"获取某个用户的当前WebSocket连接;给某个WebSocket连接发送消息;为所有WebSocket连接发送消息等等

import com.td.yousan.util.StringUtils;
import org.java_websocket.WebSocket;
import java.util.*;
public class WsPool {
 private static final Map<WebSocket, String> wsUserMap = new HashMap<WebSocket, String>();
 /**
  * 通过websocket连接获取其对应的用户
  */
 public static String getUserByWs(WebSocket conn) {
  return wsUserMap.get(conn);
 }
 /**
  * 根据userName获取WebSocket,这是一个list,此处取第一个
  * 因为有可能多个websocket对应一个userName(但一般是只有一个,因为在close方法中,我们将失效的websocket连接去除了)
  */
 public static WebSocket getWsByUser(String userName) {
  Set<WebSocket> keySet = wsUserMap.keySet();
  synchronized (keySet) {
   for (WebSocket conn : keySet) {
    String cuser = wsUserMap.get(conn);
    if (cuser.equals(userName)) {
     return conn;
    }
   }
  }
  return null;
 }
 /**
  * 向连接池中添加连接
  */
 public static void addUser(String userName, WebSocket conn) {
  wsUserMap.put(conn, userName); // 添加连接
 }
 /**
  * 获取所有连接池中的用户,因为set是不允许重复的,所以可以得到无重复的user数组
  */
 public static Collection<String> getOnlineUser() {
  List<String> setUsers = new ArrayList<String>();
  Collection<String> setUser = wsUserMap.values();
  for (String u : setUser) {
   setUsers.add(u);
  }
  return setUsers;
 }
 /**
  * 移除连接池中的连接
  */
 public static boolean removeUser(WebSocket conn) {
  if (wsUserMap.containsKey(conn)) {
   wsUserMap.remove(conn); // 移除连接
   return true;
  } else {
   return false;
  }
 }
 /**
  * 向特定的用户发送数据
  */
 public static void sendMessageToUser(WebSocket conn, String message) {
  if (null != conn && null != wsUserMap.get(conn)) {
   conn.send(message);
  }
 }
 /**
  * 向所有用户名中包含某个特征得用户发送消息
  */
 public static void sendMessageToSpecialUser(String message,String special) {
  Set<WebSocket> keySet = wsUserMap.keySet();
  if (special == null) {
   special = "";
  }
  synchronized (keySet) {
   for (WebSocket conn:keySet) {
    String user = wsUserMap.get(conn);
    try {
     if (user != null) {
      String [] cus = user.split("_");
      if (!StringUtils.isNullOrEmpty(cus[0])) {
       String cusDot = "," + cus[0] + ",";
       if (cusDot.contains(","+special+",")) {
         conn.send(message);
       }
      }else {
       conn.send(message);
      }
     }
    }catch (Exception e) {
     e.printStackTrace();
     //wsUserMap.remove(conn);
    }
   }
  }
 }
 /**
  * 向所有的用户发送消息
  */
 public static void sendMessageToAll(String message) {
  Set<WebSocket> keySet = wsUserMap.keySet();
  synchronized (keySet) {
   for (WebSocket conn : keySet) {
    String user = wsUserMap.get(conn);
    if (user != null) {
     conn.send(message);
    }
   }
  }
 }
}

总结

以上所述是小编给大家介绍的微信小程序使用websocket通讯的demo,含前后端代码,亲测可用,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

Javascript 相关文章推荐
js DOM模型操作
Dec 28 Javascript
js实现的跟随鼠标移动的时钟效果(中英文日期显示)
Jan 17 Javascript
一个可拖拽列宽表格实例演示
Nov 26 Javascript
jQuery()方法的第二个参数详解
Apr 29 Javascript
JS判断来路是否是百度等搜索索引进行弹窗或自动跳转的实现代码
Oct 09 Javascript
Json按某个键的值进行排序
Dec 22 Javascript
JavaScript中捕获与冒泡详解及实例
Feb 03 Javascript
js自定义Tab选项卡效果
Jun 05 Javascript
使用typescript开发angular模块并发布npm包
Apr 19 Javascript
layui--select使用以及下拉框实现键盘选择的例子
Sep 24 Javascript
Angular封装表单控件及思想总结
Dec 11 Javascript
vue+elementUI组件table实现前端分页功能
Nov 15 Javascript
微信小程序登录态和检验注册过没的app.js写法
May 22 #Javascript
element-ui上传一张图片后隐藏上传按钮功能
May 22 #Javascript
微信小程序非跳转式组件授权登录的方法示例
May 22 #Javascript
小程序rich-text组件如何改变内部img图片样式的方法
May 22 #Javascript
JavaScript中的 new 命令
May 22 #Javascript
element-ui组件中input等的change事件中传递自定义参数
May 22 #Javascript
原生JS实现列表内容自动向上滚动效果
May 22 #Javascript
You might like
一些星际专用术语解释
2020/03/04 星际争霸
收集的php编写大型网站问题集
2007/03/06 PHP
php操作SVN版本服务器类代码
2011/11/27 PHP
解析php中heredoc的使用方法
2013/06/17 PHP
解决php接收shell返回的结果中文乱码问题
2014/01/23 PHP
EarthLiveSharp中cloudinary的CDN图片缓存自动清理python脚本
2017/04/04 PHP
php PDO属性设置与操作方法分析
2018/12/27 PHP
PHP XML Expat解析器知识点总结
2019/02/15 PHP
用javascript实现读取txt文档的脚本
2007/07/20 Javascript
js中 关于undefined和null的区别介绍
2013/04/16 Javascript
js 判断计算字符串长度/判断空的简单方法
2013/08/05 Javascript
js中创建对象的几种方式示例介绍
2014/01/26 Javascript
iframe实用操作锦集
2014/04/22 Javascript
JS鼠标拖拽实例分析
2015/11/23 Javascript
网络传输协议(http协议)
2016/11/18 Javascript
bootstrap的工具提示实例代码
2017/05/17 Javascript
用纯Node.JS弹出Windows系统消息提示框实例(MessageBox)
2017/05/17 Javascript
带你快速理解javascript中的事件模型
2017/08/14 Javascript
微信小程序自定义tab实现多层tab嵌套功能
2018/06/15 Javascript
jQuery each和js forEach用法比较
2019/02/27 jQuery
详解在Vue.js编写更好的v-for循环的6种技巧
2020/04/14 Javascript
[40:50]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS LGD第四场
2014/05/24 DOTA
[56:29]Secret vs Optic 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
Python正则表达式指南 推荐
2018/10/09 Python
python仿evething的文件搜索器实例代码
2019/05/13 Python
Python完成毫秒级抢淘宝大单功能
2019/06/06 Python
PyQt5 QListWidget选择多项并返回的实例
2019/06/17 Python
python Kmeans算法原理深入解析
2019/08/23 Python
基于Tensorflow使用CPU而不用GPU问题的解决
2020/02/07 Python
python3.7 openpyxl 在excel单元格中写入数据实例
2020/09/01 Python
C#公司笔试题
2014/03/28 面试题
优秀大学生的自我评价
2014/01/16 职场文书
新学期开学演讲稿
2014/05/24 职场文书
期末复习计划
2015/01/19 职场文书
2015年爱国卫生月活动总结
2015/03/26 职场文书
vue使用element-ui按需引入
2022/05/20 Vue.js