- guacamole的安装
pip install pyguacamole
通过pip的方式直接安装,本次使用的是pyguacamole 0.8,django的版本是3.0.5
- 具体的实现方法
django后端要用socket的连接方式,由于websocket已经停止更新了,所以通过用channels来建立socket连接,本代码实现的是前后端分离的项目结构
项目结构如下图
其中center文件夹下的 guacamoleclient.py的具体代码如下
from threading import Thread
from django.conf import settings
# from asgiref.sync import async_to_sync
import time
import traceback
from guacamole.client import GuacamoleClient, PROTOCOLS
# from guacamole.exceptions import GuacamoleError
# from guacamole.instruction import GuacamoleInstruction as Instruction
import sys
import os
import base64
#import logging
#logging.basicConfig(level=logging.INFO, format='[%(asctime)s] - %(name)s - %(levelname)s - %#(message)s')
#logger = logging.getLogger(__name__)
class Client:
def __init__(self, websocker):
self.websocker = websocker
self.guacamoleclient = None
def connect(self, protocol, hostname, port, username, password, width, height, dpi, **kwargs):
try:
self.guacamoleclient = GuacamoleClient(
settings.GUACD.get('host'),
settings.GUACD.get('port'),
settings.GUACD.get('timeout'),
)
self.guacamoleclient.handshake(
protocol=protocol,
hostname=hostname,
port=port,
password=password,
width=width,
height=height,
dpi=dpi,
ignore_cert="true",
disable_audio="true",
# client_name="devops",
**kwargs,
)
Thread(target=self.websocket_to_django).start()
except Exception:
logger.error(traceback.format_exc())
self.websocker.close(3001)
def django_to_guacd(self, data):
try:
self.guacamoleclient.send(data)
except Exception:
self.close()
def websocket_to_django(self):
try:
while 1:
# time.sleep(0.00001)
data = self.guacamoleclient.receive()
if not data:
print('connect offline...')
break
else:
# print('conncet ok............')
self.websocker.send(data)
except Exception as e:
print(e)
finally:
self.close()
def close(self):
try:
self.websocker.close()
self.guacamoleclient.close()
except Exception:
logger.error(traceback.format_exc())
def shell(self, data):
self.django_to_guacd(data)
center文件夹下的consumers.py文件的具体代码如下
import time
import json
from channels.generic.websocket import WebsocketConsumer, AsyncWebsocketConsumer
from asgiref.sync import async_to_sync
import redis
from asgiref.sync import sync_to_async
import asyncio #socket要实现自动循环推送消息给前端的话,如果用异步的话,延时要用这个
import threading
import re
import base64
from django.http.request import QueryDict
import os
import shutil
from .guacamoleclient import Client
from guacamole.client import GuacamoleClient
pool = redis.ConnectionPool(
host='127.0.0.1',
port=6379,
# max_connections=10,
# decode_responses=True
)
conn = redis.Redis(connection_pool=pool, decode_responses=True)
class WebGuacamole(WebsocketConsumer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# self.hostid = int(guacamole_args.get('hostid'))
# self.remote_host = None
self.width = 1024 #这边固定的显示的长宽和分辨率了,可以根据情况自己修改
self.height = 768
self.dpi = 96
self.guacamoleclient = None
self.closed = False
def connect(self):
self.accept('guacamole')
# async_to_sync(self.channel_layer.group_add)('guacamole_c', self.channel_name) # 加入组
# guacamole 连接性能参数设置
# enable_wallpaper 如果设置为true,则开启桌面壁纸渲染。默认为不开启
# enable_theming 如果设置为true,则开启窗口和控件的主题。默认为不开启
# enable_font_smoothing 如果设置为“true”,文本将以平滑的边缘呈现。默认情况下,RDP上的文本粗体呈现,因为这减少了文本使用的颜色数量,从而减少了连接所需的带宽。
# enable_full_window_drag 如果设置为“true”,窗口的内容将随着窗口的移动而显示。默认情况下,RDP服务器将仅在窗口拖动时绘制窗口边框。
# enable_desktop_composition 如果设置为“true”,则允许使用透明窗口和阴影等图形效果。默认情况下,此类效果(如果可用)被禁用。
# enable_menu_animations 如果设置为“true”,菜单开启和关闭动画将被允许。默认情况下禁用菜单动画。
self.guacamoleclient = Client(websocker=self)
self.guacamoleclient.connect(
protocol='vnc', #这边选择的远程连接方式为vnc,也可以用rdp
hostname='10.200.130.9', #这边先固定一个ip,可以根据实际情况去修改
port=5900, #该台的端口号
username='vnc', #该台的登入账号
password=1234567890, #该台的登入密码
width=self.width,
height=self.height,
dpi=self.dpi,
enable_font_smoothing="true",
# enable_wallpaper="true",
# enable_theming="true",
# enable_full_window_drag="true",
# enable_desktop_composition="true",
# enable_menu_animations="true",
)
# t = threading.Thread(target=self.check_timeout)
# t.daemon = True
# t.start()
def disconnect(self, close_code):
self.guacamoleclient.close()
def receive(self, text_data=None, bytes_data=None):
self.guacamoleclient.shell(text_data)
def check_timeout(self, sleep_time=3):
while 1:
if self.closed:
break
time.sleep(sleep_time)
center文件夹下的routing.py文件的具体代码如下
# mysite/chat/routing.py
from django.urls import re_path, path
from . import consumers
websocket_urlpatterns = [
#re_path(r"ws/center/(?P<power>\w+)/(?P<user_id>\w+)/$", consumers.*********),
re_path('ws/webguacamole/', consumers.WebGuacamole),
]
django的setting文件下centercontrol文件下下也要配置一个routing.py文件,具体代码如下:
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
# from center import routing
import center.routing
application = ProtocolTypeRouter({
"websocket": AuthMiddlewareStack(
URLRouter(
center.routing.websocket_urlpatterns
)
),
})
到这里就实现了前后端分离,后端代码了。