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

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,含前后端代码,亲测可用的更多相关文章
- 微信小程序图片上传java后台(前后端代码)
小程序代码 upload:function(e){ var that = this; wx.showActionSheet({ itemList: ['从相册选择','拍照'], itemColor: ...
- 微信小程序之WebSocket
本文版权归 OSChina jsongo0 所有,转载请标明出处,以示尊重! 原文:https://my.oschina.net/jsongo/blog/757871 为什么需要websocket?传 ...
- PHP小程序后端支付代码亲测可用
小程序后端支付代码亲测可用 <?php namespace Home\Controller; use Think\Controller; class WechatpayController ex ...
- 微信小程序之最简单的Demo设计使用
这个小Demo,代码量不多:导航样式.View.Text.点击.JS交互的使用,主要是理解每个后缀文件的功能,然后才能更好的使用开发.......(下面代码和源代码没差别,实在想要的请留言,谢谢... ...
- 微信小程序开发——websocket测试
服务端 在windows下执行 node server.js 也可参照我的前一篇部署https var httpServ = require('http') var WebSocketServer ...
- 微信小程序和微信小程序之间的跳转和传参示例代码附讲解
一:微信小程序跳转 使用限制 需要用户触发跳转 从 2.3.0 版本开始,若用户未点击小程序页面任意位置,则开发者将无法调用此接口自动跳转至其他小程序. 需要用户确认跳转 从 2.3.0 版本开始,在 ...
- GitHub Top 微信小程序——在家中憋了几天写点代码吧
GitHub Top 本项目为 GitHub 热点项目微信小程序客户端,首页仅推荐一个热点项目,这个项目往往是社会热门事件所催生的一个项目,如 996.ICU.wuhan2020,所推荐项目标准为:积 ...
- 基于vs2015 SignalR开发的微信小程序使用websocket实现聊天功能
一)前言 在微信小程上实现聊天功能,大致有三种方式:1)小程序云开发 2)购买第三方IM服务 3)使用自己的服务器自己开发. 这里重要讲使用自己的服务器自己开发,并且是基于vs的开发. 网上提供的解决 ...
- 微信小程序之支付密码输入demo
在小程序中实现支付密码的输入,要解决几个问题: 1.小程序要想唤起键盘,必须要借助input控件.通过input控件和其属性focus来唤起和隐藏输入键盘. 2.要让input控件不可见.让光标和输入 ...
随机推荐
- 使用Spring访问Mongodb的方法大全——Spring Data MongoDB
1.概述 Spring Data MongoDB 是Spring框架访问mongodb的神器,借助它可以非常方便的读写mongo库.本文介绍使用Spring Data MongoDB来访问mongod ...
- Shell脚本(1)
在创建Shell脚本时,必须在文件的第一行指定要使用的shell.格式为:#!/bin/bash 除了第一行外,在shell脚本中井号(#)用作注释行 若出现错误:command not found ...
- KETTLE入门教程-单表读取
kettle初探 Kettle简介:Kettle是一款国外开源的ETL工具,纯java编写,可以在Window.Linux.Unix上运行,数据抽取高效稳定.Kettle 中文名称叫水壶,该项目的主程 ...
- 【cf343】D. Water Tree(dfs序+线段树)
传送门 题意: 给出一个以\(1\)为根的有根树,起始每个结点都为\(0\),现在有三种操作: 1.将\(v\)及\(v\)的子树都置为\(1\): 2.将\(v\)及其所有的祖先都置为\(0\): ...
- 深浅拷贝及 join set
1.join s="**".join (['风清扬',"独孤求败"] ) join 把里面的东西拿出来,进行拼接 s="_". ...
- Linux 中find命令
1.在当前目录下找以txt结尾的文件 find . -name '*.txt' 2.在当前目录下找以所有字母开头的文件 find . -name '[a-z]*' 3.在/etc 目录下找以host开 ...
- day79_10_28git使用基础
一.git与svn比较. git就是版本控制器,控制的对象是开发的项目代码. 可以根具时间轴进行回滚代码,改变代码版本. svn的特点就是服务版与用户版分离,当开发这需要进行开发时,需要先在代码仓库中 ...
- lua 11 闭包,函数的使用
转自:http://book.luaer.cn/_41.htm 当一个函数内部嵌套另一个函数定义时,内部的函数体可以访问外部的函数的局部变量,这种特征我们称作词法定界.虽然这看起来很清楚,事实并非如此 ...
- Python 栈(stack)
Python 栈(stack) 栈(stack)又名堆栈,它是一种运算受限的线性表 栈只能在一端进行插入和删除操作,它按照先进后出(FILO)的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶 ...
- SVN 中项目名字全是红色 和 文件夹图标上没标记绿钩解决办法
没有绿色标记卸载Tortoise 小乌龟重装 ! 红色名字是 原来idea当前的project用了版本控制器, 那么建到这个project下面的所有项目就都是加入到版本控制里面的, ...