微信小程序使用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 相关文章推荐
javascript+xml技术实现分页浏览
Jul 27 Javascript
最佳JS代码编写的14条技巧
Jan 09 Javascript
input file上传 图片预览功能实例代码
Oct 25 Javascript
将angular.js项目整合到.net mvc中的方法详解
Jun 29 Javascript
详解基于vue的移动web app页面缓存解决方案
Aug 03 Javascript
详解VueJS应用中管理用户权限
Feb 02 Javascript
微信小程序实现文字跑马灯效果
May 26 Javascript
jQuery实现图片简单轮播功能示例
Aug 13 jQuery
node.js使用免费的阿里云ip查询获取ip所在地【推荐】
Sep 03 Javascript
小程序转发探索示例
Feb 19 Javascript
微信小程序设置滚动条过程详解
Jul 25 Javascript
vant 中van-list的用法说明
Nov 11 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/08/18 杂记
php防攻击代码升级版
2010/12/29 PHP
深入PHP FTP类的详解
2013/06/13 PHP
PHP内核探索之变量
2015/12/22 PHP
php源码的使用方法讲解
2019/09/26 PHP
扩展Jquery插件处理mouseover时内部有子元素时发生样式闪烁
2011/12/08 Javascript
ajax页面无刷新 IE下遭遇Ajax缓存导致数据不更新的问题
2012/12/11 Javascript
Jquery post传递数组方法实现思路及代码
2013/04/28 Javascript
js获取电脑分辨率的思路及操作
2013/11/22 Javascript
jQuery选择器简明总结(含用法实例,一目了然)
2014/04/25 Javascript
jQuery获取radio选中项的值实例
2016/06/18 Javascript
JavaScript结合HTML DOM实现联动菜单
2017/04/05 Javascript
bootstrap table方法之expandRow-collapseRow展开或关闭当前行数据
2020/08/09 Javascript
微信小程序实现验证码获取倒计时效果
2018/02/08 Javascript
js实现图片放大并跟随鼠标移动特效
2019/01/18 Javascript
vue路由传参页面刷新参数丢失问题解决方案
2019/10/08 Javascript
vue props对象validator自定义函数实例
2019/11/13 Javascript
vue开发中遇到的问题总结
2020/04/07 Javascript
vue 数据双向绑定的实现方法
2021/03/04 Vue.js
[01:42]辉夜杯战队访谈宣传片—FANTUAN
2015/12/25 DOTA
python处理文本文件并生成指定格式的文件
2014/07/31 Python
python自定义类并使用的方法
2015/05/07 Python
Window10+Python3.5安装opencv的教程推荐
2018/04/02 Python
python 判断参数为Nonetype类型或空的实例
2018/10/30 Python
python tkinter图形界面代码统计工具
2019/09/18 Python
Python Process多进程实现过程
2019/10/22 Python
如何将json数据转换为python数据
2020/09/04 Python
英国骑行、跑步、游泳、铁人三项运动装备专卖店:Wiggle
2016/08/23 全球购物
Raffaello Network德国:意大利拉斐尔时尚购物网
2019/05/01 全球购物
htmlentities() 和 htmlspecialchars()有什么区别
2015/07/01 面试题
北京银河万佳Java面试题
2012/03/21 面试题
应用化学专业本科生求职信
2013/09/29 职场文书
给医务人员表扬信
2014/01/12 职场文书
保护环境倡议书
2014/04/14 职场文书
2016年国庆节宣传标语
2015/11/25 职场文书
用Python编写简单的gRPC服务的详细过程
2021/07/04 Python