微信小程序使用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 &amp;&amp;和||运算法的另类使用技巧
Nov 28 Javascript
ie浏览器使用js导出网页到excel并打印
Mar 11 Javascript
jquery实现图片按比例缩放示例
Jul 01 Javascript
Javascript冒泡排序算法详解
Dec 03 Javascript
js由下向上不断上升冒气泡效果实例
May 07 Javascript
jQuery实现淡入淡出二级下拉导航菜单的方法
Aug 28 Javascript
js发送短信倒计时的简单实现方法
Sep 08 Javascript
vue数据控制视图源码解析
Mar 28 Javascript
jquery-ui 进度条功能示例【测试可用】
Jul 25 jQuery
javascript 构建模块化开发过程解析
Sep 11 Javascript
vue.config.js中配置Vue的路径别名的方法
Feb 11 Javascript
js判断两个数组相等的5种方法
May 06 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实现长连接的方法与注意事项的问题
2013/05/10 PHP
php class中public,private,protected的区别以及实例分析
2013/06/18 PHP
ecshop 2.72如何修改后台访问地址
2015/03/03 PHP
laravel创建类似ThinPHP中functions.php的全局函数
2016/11/26 PHP
php新建文件的方法实例
2019/09/26 PHP
javascript学习笔记(四) Number 数字类型
2012/06/19 Javascript
Ext JS 4实现带week(星期)的日期选择控件(实战一)
2013/08/21 Javascript
js简单实现交换Li的值
2014/05/22 Javascript
js调试工具Console命令详解
2014/10/21 Javascript
javascript框架设计读书笔记之字符串的扩展和修复
2014/12/02 Javascript
jQuery实现非常实用漂亮的select下拉菜单选择效果
2015/11/06 Javascript
浅谈EasyUi ComBotree树修改 父节点选择的问题
2016/11/07 Javascript
JS扩展类,克隆对象与混合类实例分析
2016/11/26 Javascript
基于JavaScript定位当前的地理位置
2017/04/11 Javascript
使用prop解决一个checkbox选中后再次选中失效的问题
2017/07/05 Javascript
基于input动态模糊查询的实现方法
2017/12/12 Javascript
mock.js实现模拟生成假数据功能示例
2019/01/15 Javascript
[02:52]DOTA2新手基础教程 米波
2014/01/21 DOTA
Python二叉树的定义及常用遍历算法分析
2017/11/24 Python
Python学习_几种存取xls/xlsx文件的方法总结
2018/05/03 Python
python 并发编程 阻塞IO模型原理解析
2019/08/20 Python
Python 用三行代码提取PDF表格数据
2019/10/13 Python
收藏!10个免费高清视频素材网站!【设计、视频剪辑必备】
2021/03/18 杂记
HTML5的结构和语义(3):语义性的块级元素
2008/10/17 HTML / CSS
德国最大的网上鞋店之一:Schuhe24.de
2017/06/10 全球购物
Surfdome西班牙:世界上最受欢迎的生活方式品牌
2019/02/13 全球购物
俄罗斯童装网上商店:BebaKids
2020/06/06 全球购物
不开辟用于交换数据的临时空间,如何完成字符串的逆序
2012/12/02 面试题
公司领导推荐信
2013/11/12 职场文书
优秀女职工事迹材料
2014/02/06 职场文书
辞旧迎新演讲稿
2014/09/15 职场文书
收款授权委托书
2014/10/02 职场文书
道路交通事故人身损害赔偿协议书
2014/11/19 职场文书
2016年小学植树节活动总结
2016/03/16 职场文书
浅谈Go语言多态的实现与interface使用
2021/06/16 Golang
Python字符串的转义字符
2022/04/07 Python