vue 建立websocket连接
需求:管理后台需要服务器建立长连接,发送远程手机端的截图,以此实现远程手机屏幕共享的功能。后端 使用的java进行处理。
·
需求:管理后台需要服务器建立长连接,发送远程手机端的截图,以此实现远程手机屏幕共享的功能
websocket.js
let Socket = null
let setIntervalWesocketPush = null
const socketUrl = 'ws:127.0.0.1:8080/goLink/manager/' // socket连接地址
import store from '@/store'
/**
* 建立websocket连接
* @param {string} url ws地址
*/
export const createSocket = () => {
Socket && Socket.close()
if (!Socket) {
console.log('建立websocket连接')
let userid = store.state.user.name;// 这里我是为了获取登录的用户信息
if(userid){
Socket = new WebSocket(socketUrl+userid)
Socket.onopen = onopenWS
Socket.onmessage = onmessageWS
Socket.onerror = onerrorWS
Socket.onclose = oncloseWS
}else {
this.$message.error("websocket连接失败,未获取到账户信息")
}
} else {
console.log('websocket已连接')
}
}
/**打开WS之后发送心跳 */
const onopenWS = () => {
// sendPing()
}
/**连接失败重连 */
const onerrorWS = () => {
Socket.close()
clearInterval(setIntervalWesocketPush)
console.log('连接失败重连中')
if (Socket.readyState !== 3) {
Socket = null
createSocket(socketUrl)
}
}
/**WS数据接收统一处理 */
const onmessageWS = e => {
window.dispatchEvent(new CustomEvent('onmessageWS', {
detail: {
data: e.data
}
}))
}
/**
* 发送数据但连接未建立时进行处理等待重发
* @param {any} message 需要发送的数据
*/
const connecting = message => {
setTimeout(() => {
if (Socket.readyState === 0) {
connecting(message)
} else {
Socket.send(JSON.stringify(message))
}
}, 1000)
}
/**
* 发送数据
* @param {any} message 需要发送的数据
*/
export const sendWSPush = message => {
if (Socket !== null && Socket.readyState === 3) {
Socket.close()
createSocket(socketUrl)
} else if (Socket.readyState === 1) {
Socket.send(JSON.stringify(message))
} else if (Socket.readyState === 0) {
connecting(message)
}
}
/**断开重连 */
const oncloseWS = () => {
console.log('websocket已断开')
Socket = null
/*clearInterval(setIntervalWesocketPush)
console.log('websocket已断开....正在尝试重连')
if (Socket.readyState !== 2) {
Socket = null
createSocket()
}*/
}
export const closeWs =() =>{
Socket.close()
}
/**发送心跳
* @param {number} time 心跳间隔毫秒 默认5000
* @param {string} ping 心跳名称 默认字符串ping
*/
export const sendPing = (time = 5000, ping = 'ping') => {
clearInterval(setIntervalWesocketPush)
Socket.send(JSON.stringify({"event":"heart"}))
setIntervalWesocketPush = setInterval(() => {
Socket.send(JSON.stringify({"event":"heart"}))
}, time)
}
页面
在vue 添加方法
import { createSocket,sendWSPush,closeWs } from '../../../utils/websocket'
wsConnect(){
createSocket()
this.getsocketData = (e) => {
// 创建接收消息函数
let data = e && e.detail.data
if(data){
console.log(data)
let json = JSON.parse(data);
if (json.event == 'open') {// 已经建立了连接
this.dialogVisible = true
let msg = {"event":'open_screen',"to_user":this.userId}
sendWSPush(msg)
}
}
}
// 注册监听事件
window.addEventListener('onmessageWS', this.getsocketData)
},
handleClose(){
//想服务器发送断开连接的信息
let msg = {"event":'stop_screen',"to_user":this.userId}
sendWSPush(msg)
closeWs()
this.dialogVisible = false
window.removeEventListener('onmessageWS',this.getsocketData)
},
screenSharing(userid){
this.userId = userid
this.wsConnect()
},
后端 使用的java进行处理
package io.renren.modules.xmkj.handler;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.renren.common.utils.SpringContextUtils;
import io.renren.modules.xmkj.dto.ResultDto;
import io.renren.modules.xmkj.entity.ScriptEntity;
import io.renren.modules.xmkj.entity.SqPhonesEntity;
import io.renren.modules.xmkj.entity.YyzsTaskLogsEntity;
import io.renren.modules.xmkj.entity.YyzsTaskScriptEntity;
import io.renren.modules.xmkj.service.ScriptService;
import io.renren.modules.xmkj.service.SqPhonesService;
import io.renren.modules.xmkj.service.YyzsTaskLogsService;
import io.renren.modules.xmkj.service.YyzsTaskScriptService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* 自动化运营后台
*/
@ServerEndpoint(value ="/goLink/manager/{userId}") // 通过这个 spring boot 就可以知道你暴露出去的 ws 应用的路径,有点类似我们经常用的@RequestMapping。比如你的启动端口是8080,而这个注解的值是ws,那我们就可以通过 ws://127.0.0.1:8080/ws 来连接你的应用
@Component
@Slf4j
public class WebSocketManagerHandler {
/**
* 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
*/
private static int onlineCount = 0;
/**
* concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
*/
private static ConcurrentHashMap<String, WebSocketManagerHandler> webSocketMap = new ConcurrentHashMap<>();
/**
* 与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
private Session session;
/**
* 接收userId
*/
private String userId = "";
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam("userId") String userId) {
this.session = session;
this.userId = userId;
// this.source = source;
if(userId==null){
log.error("无userId");
serverClose();
}else {
//连接
if (webSocketMap.containsKey(userId)) {
webSocketMap.remove(userId);
//加入set中
webSocketMap.put(userId, this);
} else {
//加入set中
webSocketMap.put(userId, this);
//在线数加1
addOnlineCount();
}
log.info("用户连接:" + userId + ",当前在线人数为:" + getOnlineCount());
try {
JSONObject json = new JSONObject();
json.put("event","open");
json.put("msg","ok");
sendMessage(json.toJSONString());
} catch (IOException e) {
log.error("用户:" + userId + ",网络异常!!!!!!");
}
}
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
if (webSocketMap.containsKey(userId)) {
webSocketMap.remove(userId);
//从set中删除
subOnlineCount();
}
log.info("用户退出:" + userId + ",当前在线人数为:" + getOnlineCount());
}
/**
* 主动断开连接
*/
public void serverClose(){
try {
this.session.close();
this.onClose();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("用户消息:" + userId + ",报文:" + message);
//可以群发消息
//消息保存到数据库、redis
if (StringUtils.isNotBlank(message)) {
try {
//解析发送的报文
JSONObject jsonObject = JSON.parseObject(message);
switch (jsonObject.getString("event")){
case "heart":{
//检查当前的手机是否有执行的自动化任务
break;
}
case "open_screen":{
//检查当前的手机是否有执行的自动化任务
String to_user = jsonObject.getString("to_user");
ResultDto res = new ResultDto();
res.setEvent("open_screen");
res.setFromUser(userId);//来自服务器
WebSocketDHZSHandler.sendInfo(JSON.toJSONString(res),to_user);
break;
}
case "stop_screen":{
String to_user = jsonObject.getString("to_user");
ResultDto res = new ResultDto();
res.setEvent("stop_screen");
res.setFromUser(userId);//来自服务器
WebSocketDHZSHandler.sendInfo(JSON.toJSONString(res),to_user);
break;
}
default:
JSONObject jsonRes = new JSONObject();
jsonRes.put("fromuserId", "system");
jsonRes.put("event", "heart");
jsonRes.put("msg", "event无法处理");
sendMessage(jsonRes.toJSONString());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("用户错误:" + this.userId + ",原因:" + error.getMessage());
error.printStackTrace();
}
/**
* 实现服务器主动推送
*/
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
/**
* 发送自定义消息
*/
public static boolean sendInfo(String message, @PathParam("userId") String userId) throws IOException {
log.info("发送消息到:" + userId + ",报文:" + message);
boolean flag = false;
if (StringUtils.isNotBlank(userId) && webSocketMap.containsKey(userId)) {
webSocketMap.get(userId).sendMessage(message);
return !flag;
} else {
log.error("用户" + userId + ",不在线!");
return flag;
}
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketManagerHandler.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketManagerHandler.onlineCount--;
}
}
实现的效果
点击关闭按钮时 断开连接
更多推荐
所有评论(0)