前端Vue中使用Guacamole进行远程桌面的前端部分

news/2024/12/16 21:37:14/

最近公司有个项目要求远程虚拟机,最后选择使用了Guacamole进行实现,网上搜了一下感觉资料不是很多,对guacamole-common.js里的API介绍也没查到(捂脸),可能是我的问题。网上的教程都是教后端怎么搭建远程桌面系统。对web端使用的资料很少,可能大佬们觉着不需要(╥╯^╰╥)。下面我把在项目中用到的一下方法,总结一下,万一有人也需要呐。哈哈

  1. 下载guacamole-common或者直接引入guacamole-common.js文件;

  2. 在项目中的引用

    初始化Guacamole
    const initGuacamole = () => {
    // XXXXX 后端提供的连接地址
    guacamole.tunnel = new Guacamole.WebSocketTunnel(‘XXXXX’)

      if (guacamole.client) {guacamole.display.scale(0)uninstallKeyboard()}guacamole.client = new Guacamole.Client(guacamole.tunnel)guacamole.tunnel.onerror = error => {// console.error(`Tunnel failed ${JSON.stringify(error)}`)// 这里是断开重连的机智 当code值是下面这些时会进行重连5次,if (error.code === 512 || error.code === 514 || error.code === 515 || error.code === 769 || error.code === 776) {if (guacamole.curRetryCount === 0) {guacamole.retryTask = setInterval(() => {if (guacamole.curRetryCount < guacamole.maxRetryCount) {uninstallKeyboard()nextTick(() => {initGuacamole('error')})guacamole.curRetryCount++} else if (guacamole.curRetryCount >= guacamole.maxRetryCount) {guacamole.loading = falseguacamole.loadingText = ''uninstallKeyboard()clearInterval(guacamole.retryTask)guacamole.retryTask = null}}, 3000)}}else {if (!guacamole.retryTask) {guacamole.loading = falseguacamole.loadingText = ''}}}guacamole.tunnel.onstatechange = state => {// console.log('tunnel.onstatechange',Guacamole.Tunnel.State,state);switch (state) {case Guacamole.Tunnel.State.CONNECTING:guacamole.connectionState = TUNNEL_STATES.CONNECTINGbreak;// Connection is established / no longer unstablecase Guacamole.Tunnel.State.OPEN:guacamole.connectionState = TUNNEL_STATES.CONNECTEDbreak;// Connection is established but misbehavingcase Guacamole.Tunnel.State.UNSTABLE:// TODOguacamole.connectionState = '不稳定'// this.$message.error("不稳定")break;// Connection has closedcase Guacamole.Tunnel.State.CLOSED:guacamole.connectionState = TUNNEL_STATES.DISCONNECTEDbreak;}}guacamole.client.onstatechange = clientState => {// console.log('clientState', clientState,  TUNNEL_STATES);switch (clientState) {case 0:guacamole.connectionState = TUNNEL_STATES.IDLEbreakcase 1:// connecting ignored for some reason?breakcase 2:guacamole.connectionState = TUNNEL_STATES.WAITINGbreakcase 3:guacamole.connectionState = TUNNEL_STATES.CONNECTED// 取消加载guacamole.loading = falseguacamole.loadingText = ''// 重连清空定时器和次数guacamole.curRetryCount = 0clearInterval(guacamole.retryTask)guacamole.retryTask = null//监听视图变化,并发送最新的宽高给Guacamole进行重新绘制window.addEventListener('resize', resize)case 4:case 5:// disconnected, disconnectingbreak}}guacamole.client.onerror = error => {guacamole.client.disconnect()console.error(`Client error ${JSON.stringify(error)}`)}guacamole.display = guacamole.client.getDisplay()display.value.appendChild(guacamole.display.getElement())display.value.addEventListener('contextmenu', e => {e.stopPropagation();if (e.preventDefault) {e.preventDefault();}e.returnValue = false;})// 后端需要的参数let param = {userName: '',password: '',type: 'VNC/RDP'}guacamole.client.connect(param);// 视图大小发生变化时触发(rdp和VNC同时连接时rdp可以动态设置分辨率,但是VNC不可以,所以前端可以通过onresize拿到rdp连接后,VNC通道拿到流的宽高进行等比缩放)guacamole.display.onresize = function(width, height) {const resizeScale = Math.min(viewport.value.clientWidth / Math.max(guacamole.display.getWidth(), 1), viewport.value.clientHeight / Math.max(guacamole.display.getHeight(), 1))guacamole.display.scale(resizeScale)}window.onunload = () => guacamole.client.disconnect();// 解决连接多个虚拟机时有的虚拟机不能查看z-index: -1guacamole.client.getDisplay().scale(1)display.value.onclick = () => {display.value.focus()}display.value.onfocus = () => {display.value.className = 'focus'}display.value.onblur = () => {display.value.className = ''}guacamole.keyboard = new Guacamole.Keyboard(display.value);installKeyboard()// Mouse 参数最好使用guacamole.client.getDisplay().getElement(),之前写的是父级元素,会导致出现两个鼠标的问题guacamole.mouse = new Guacamole.Mouse(guacamole.client.getDisplay().getElement());// 鼠标离开显示器时隐藏软件光标guacamole.mouse.onmouseout = () => {if (!guacamole.display) return;guacamole.display.showCursor(false);}guacamole.mouse.onmousedown = guacamole.mouse.onmouseup = guacamole.mouse.onmousemove = handleMouseStatesetTimeout(() => {resize()display.value.focus()}, 1000);//居中显示(当返回的流宽高小于屏幕宽高时)guacamole.client.getDisplay().getElement().style.setProperty('margin', 'auto')
    }
    
  3. 缩放方法

    const resize = () => {
    const elm = viewport.value;
    if (!elm || !elm.offsetWidth) {
    return
    }
    // let pixelDensity = window.devicePixelRatio || 1 (pixelDensity 获取当前电脑的分辨率百分比)
    let pixelDensity = 1
    const width = elm.clientWidth * pixelDensity
    const height = elm.clientHeight * pixelDensity
    if (guacamole.display.getWidth() !== width || guacamole.display.getHeight() !== height) {
    guacamole.client.sendSize(width, height)
    }
    // setting timeout so display has time to get the correct size
    setTimeout(() => {
    // 计算缩放比例
    const scale = Math.min(
    elm.clientWidth / Math.max(guacamole.display.getWidth(), 1),
    elm.clientHeight / Math.max(guacamole.display.getHeight(), 1)
    )
    // guacamole.display.scale(1)
    if (props.websocketUrl === ‘/webSocket’) {
    guacamole.display.scale(1)
    }else {
    guacamole.display.scale(scale)
    }
    }, 1000)
    }

  4. html

以上就是我在项目中的使用情况
1、连接Tunnel
guacamole.tunnel = new Guacamole.WebSocketTunnel(props.websocketUrl)
2、把流放到视图中
guacamole.client = new Guacamole.Client(guacamole.tunnel)
3、监听tunnel和client 的值进行状态判断
4、把流添加到视图中
guacamole.client.getDisplay().appendChild(guacamole.display.getElement())
5、给后端传参
let param = {userName: ’ ',password: ’ '}
guacamole.client.connect(param);
6、断开虚拟机连接
guacamole.client.disconnect();
7、键盘事件
// display.value div元素
new Guacamole.Keyboard(display.value)
8、鼠标事件
new Guacamole.Mouse(guacamole.client.getDisplay().getElement());


http://www.ppmy.cn/news/1555682.html

相关文章

Spring Boot集成ShedLock实现分布式定时任务

1、什么是ShedLock&#xff1f; ShedLock 是一个 Java 库&#xff0c;通常用于分布式系统中&#xff0c;确保定时任务&#xff08;Scheduled Tasks&#xff09;在集群环境下只被某一个实例执行一次。它通过在共享资源&#xff08;例如数据库或分布式缓存&#xff09;中添加锁的…

人工智能大语言模型起源篇,低秩微调(LoRA)

上一篇: 《规模法则&#xff08;Scaling Law&#xff09;与参数效率的提高》 序言&#xff1a;您在找工作时会不会经常听到LoRA微调&#xff0c;这项技术的来源就是这里了。 &#xff08;12&#xff09;Hu、Shen、Wallis、Allen-Zhu、Li、L Wang、S Wang 和 Chen 于2021年发表…

Matlab笔记---clear、clc、clear all应用

在MATLAB中&#xff0c;clear、clc 和 clear all 是三个常用的命令&#xff0c;它们各自有不同的作用&#xff1a; clc&#xff1a; clc 命令用于清除MATLAB命令窗口中的所有输出。它不会删除任何变量、函数或文件&#xff0c;只是清除屏幕上的显示内容&#xff0c;让你可以更…

并行口的基本概念

单片机的并行口结构包括多个并行I/O端口&#xff0c;用于与外部设备进行并行数据传输。这些端口能够直接读写外部存储器、显示设备、打印机等外设的数据&#xff0c;是单片机与外界交互的重要通道。在深入探讨之前&#xff0c;我们先简要了解下单片机的基本概念。 单片机&…

Next.js 指令教程:深入理解 use-server 指令

更多有关Next.js教程&#xff0c;请查阅&#xff1a; 【目录】Next.js 独立开发系列教程-CSDN博客 目录 1. 概述 2. use-server 指令概述 2.1 什么是 use-server 指令&#xff1f; 2.2 为什么需要 use-server&#xff1f; 3. use-server 工作原理 3.1 渲染过程 3.2 动态…

《深入浅出HTTPS​​​​​​​​​​​​​​​​​》读书笔记(19):密钥

为了避免暴力破解&#xff0c;不同密码学算法的密钥应该保证一定长度&#xff0c;密钥长度足够长也不代表安全&#xff0c;密钥应该是随机、无法预测的。 从两个维度考虑&#xff1a; ◎对称加密算法、MAC算法使用的密钥就是一串数字。 ◎公开密钥算法中的密钥是一对&#x…

机器人通信:通信方式、协议、类型、场景

机器人通信是指机器人之间、机器人与人类或机器人与其他系统之间的信号传递和信息交换。其目的是实现协作、控制、监测和数据共享。以下是一些关键点&#xff1a; 通信方式&#xff1a; 无线通信&#xff1a;使用无线电波&#xff08;如Wi-Fi、蓝牙、ZigBee等&#xff09;进行数…

【银河麒麟高级服务器操作系统】有关dd及cp测试差异的现象分析详解

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://documentkylinos.cn dd现象 使用银河麒麟高级服务器操作系统执行两次…