微信小程序使用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 相关文章推荐
讲两件事:1.this指针的用法小探. 2.ie的attachEvent和firefox的addEventListener在事件处理上的区别
Apr 12 Javascript
jQuery实现类似标签风格的导航菜单效果代码
Aug 25 Javascript
基于JavaScript实现全选、不选和反选效果
Feb 15 Javascript
js中DOM三级列表(代码分享)
Mar 20 Javascript
基于JavaScript实现移动端无限加载分页
Mar 27 Javascript
Angular 4依赖注入学习教程之Injectable装饰器(六)
Jun 04 Javascript
Js中将Long转换成日期格式的实现方法
Jun 05 Javascript
谈谈为什么你的 JavaScript 代码如此冗长
Jan 30 Javascript
JavaScript怎样在删除前添加确认弹出框?
May 27 Javascript
javascript写一个ajax自动拦截并下载数据代码实例
Sep 07 Javascript
js实现图片粘贴到网页
Dec 06 Javascript
微信小程序APP的生命周期及页面的生命周期
Apr 19 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
php 上一篇,下一篇文章实现代码与原理说明
2010/05/09 PHP
CI(Codeigniter)的Setting增强配置类实例
2016/01/06 PHP
Yii2.0使用阿里云OSS的SDK上传图片、下载、删除图片示例
2017/09/20 PHP
Yii 框架控制器创建使用及控制器响应操作示例
2019/10/14 PHP
PHP Beanstalkd消息队列的安装与使用方法实例详解
2020/02/21 PHP
jquery animate 动画效果使用说明
2009/11/04 Javascript
基于jquery扩展漂亮的下拉框可以二次修改
2013/11/19 Javascript
css结合js制作下拉菜单示例代码
2014/02/27 Javascript
纯JavaScript实现的兼容各浏览器的添加和移除事件封装
2015/03/28 Javascript
jquery判断输入密码两次是否相等
2020/04/22 Javascript
第八篇Bootstrap下拉菜单实例代码
2016/06/21 Javascript
关于 jQuery Easyui异步加载tree的问题解析
2016/12/06 Javascript
JS中事件冒泡和事件捕获介绍
2016/12/13 Javascript
Javascript DOM事件操作小结(监听鼠标点击、释放,悬停、离开等)
2017/01/20 Javascript
JS中图片压缩的方法小结
2017/11/14 Javascript
构建一个JavaScript插件系统
2020/10/20 Javascript
js实现鼠标拖曳效果
2020/12/30 Javascript
Python 读写文件和file对象的方法(推荐)
2016/09/12 Python
对Python 数组的切片操作详解
2018/07/02 Python
python3学习之Splash的安装与实例教程
2018/07/09 Python
Python 动态导入对象,importlib.import_module()的使用方法
2019/08/28 Python
基于python实现复制文件并重命名
2020/09/16 Python
小白教你PyCharm从下载到安装再到科学使用PyCharm2020最新激活码
2020/09/25 Python
Python系统公网私网流量监控实现流程
2020/11/23 Python
python 批量将中文名转换为拼音
2021/02/07 Python
css3实现的多级渐变下拉菜单导航效果代码
2015/08/31 HTML / CSS
CSS3制作缩略图的详细过程
2016/07/08 HTML / CSS
canvas实现高阶贝塞尔曲线(N阶贝塞尔曲线生成器)
2018/01/10 HTML / CSS
食品销售计划书
2014/04/26 职场文书
党的群众路线教育实践活动个人整改方案
2014/09/21 职场文书
吃空饷专项整治方案
2014/10/27 职场文书
初三英语教学计划
2015/01/23 职场文书
营业员岗位职责范本
2015/04/14 职场文书
公司禁烟通知
2015/04/23 职场文书
SQL Server2019数据库之简单子查询的具有方法
2021/04/27 SQL Server
Python3的进程和线程你了解吗
2022/03/16 Python