当前位置: 首页 > news >正文

python+flask_socketio+pyautogui实现简易远程桌面功能

python+flask_socketio+pyautogui实现简易远程桌面功能

import base64
import pyautogui
from flask import Flask
import time
from flask_socketio import SocketIO, emit
from io import BytesIO
import pyperclipapp=Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'socketio = SocketIO(app)@socketio.on('connect')
def handle_connect():"""客户端连接时触发"""print('客户端已连接')emit('server_response', {'data': '连接成功'})# 连接成功后,获取最新的远程屏幕client_get_screen()@socketio.on('client_send_keyboard_input')
def client_send_keyboard_input(json):"""处理来自客户端的消息"""print('收到客户端消息:', json)# 模拟键盘输入client_input=json['data']print('客户端输入:', client_input)# typewrite只会输入字母,其他字符会被忽略pyautogui.typewrite(client_input)client_get_screen()@socketio.on('client_send_paste_key')
def client_send_paste_key(json):"""处理来自客户端的粘贴消息"""print('收到客户端粘贴消息:', json)# 模拟粘贴操作client_paste_text=json['data']print('客户端粘贴文本:', client_paste_text)# 先将文本复制到剪贴板pyperclip.copy(client_paste_text)# 模拟粘贴键pyautogui.hotkey('ctrl', 'v')client_get_screen()@socketio.on('client_get_screen')
def client_get_screen():"""处理获取远程屏幕请求"""print('收到获取远程屏幕请求')    # 循环刷新3次for i in range(5):# 延迟0.2秒time.sleep(0.2)screen = pyautogui.screenshot()# 将屏幕图片转换为base64编码buffered = BytesIO()screen.save(buffered, format="PNG")screen_base64 = base64.b64encode(buffered.getvalue()).decode('utf-8')# 发送base64编码的屏幕图片给所有客户端emit('remote_screen_update', {'data': screen_base64},broadcast=False)@socketio.on('client_click_screen')
def handle_client_click(json):"""处理来自客户端的点击事件"""print('收到客户端点击事件:', json)x, y = json['x'], json['y']# 映射到主机屏幕坐标screen_width, screen_height = pyautogui.size()x, y = int(x * screen_width), int(y * screen_height)pyautogui.moveTo(x, y)pyautogui.click(x, y)# emit('server_response', {'data': f'已点击屏幕位置: ({x}, {y})'},broadcast=False)# 点击鼠标事件后,获取最新的远程屏幕client_get_screen()@socketio.on('client_dbclick_screen')
def handle_client_dbclick(json):"""处理来自客户端的双击事件"""print('收到客户端双击事件:', json)x, y = json['x'], json['y']# 映射到主机屏幕坐标screen_width, screen_height = pyautogui.size()x, y = int(x * screen_width), int(y * screen_height)pyautogui.doubleClick(x, y)# 双击鼠标事件后,获取最新的远程屏幕client_get_screen()@socketio.on('client_send_enter_key')
def handle_client_send_enter_key():"""处理来自客户端的Enter键事件"""print('收到客户端Enter键事件')# 模拟键盘输入Enter键pyautogui.press('enter')client_get_screen()@socketio.on('client_send_delete_key')
def handle_client_send_delete_key():"""处理来自客户端的Delete键事件"""print('收到客户端Delete键事件')# 模拟键盘输入Delete键pyautogui.press('backspace')client_get_screen()@app.route('/telescreen')
def index():"""渲染主页"""return '''<!DOCTYPE html><html><head><meta lang="zh-CN"><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>teledesk</title><style>body{background-color:black;}#telescreen {position: relative;background-color:skyblue;box-shadow: 0 0 1em rgba(0, 0, 0, 0.5);border:1em solid gray;border-radius: 1em;resize: both;overflow: auto;}#remote_screen {position: relative;top: 0;left: 0;width: 100%;}#control_panel{background-color: gray;padding: 1em;border-radius: 1em;                    }button,input{margin: 0.5em;padding: 0.5em 1em;border-radius: 0.5em;border: 1px solid #666;}</style><script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script><script type="text/javascript">document.addEventListener('DOMContentLoaded', () => {// 连接到服务器const socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port);// 接收服务器消息socket.on('server_response', (data) => {console.log("收到服务器响应:", data);});// 接收远程屏幕socket.on('remote_screen_update', (data) => {console.log("收到远程屏幕:", data);// 清除旧的远程屏幕图片while (document.getElementById('telescreen').firstChild) {document.getElementById('telescreen').removeChild(document.getElementById('telescreen').firstChild);}//创建新的远程屏幕图片const remote_screen = document.createElement('img');remote_screen.id = 'remote_screen';                        remote_screen.src=` data:image/png;base64,${data.data}`;remote_screen.alt = '远程屏幕';remote_screen.addEventListener('click', (e) => {const rect = e.target.getBoundingClientRect();const x = (e.clientX - rect.left) / rect.width;const y = (e.clientY - rect.top) / rect.height;console.log(`点击位置: (${x}, ${y})`);socket.emit('client_click_screen', {x, y});});remote_screen.addEventListener('dbclick', (e) => {const rect = e.target.getBoundingClientRect();const x = (e.clientX - rect.left) / rect.width;const y = (e.clientY - rect.top) / rect.height;console.log(`点击位置: (${x}, ${y})`);socket.emit('client_dbclick_screen', {x, y});});document.getElementById('telescreen').appendChild(remote_screen);});// 绑定获取屏幕按钮事件document.getElementById('get_screen').addEventListener('click', () => {socket.emit('client_get_screen');});// 绑定发送按钮事件document.getElementById('send_button').addEventListener('click', (e) => {const input = document.getElementById('message_input');socket.emit('client_send_keyboard_input', {data: input.value});input.value = '';});// 绑定粘贴按钮事件document.getElementById('paste_button').addEventListener('click', (e) => {const input = document.getElementById('message_input');socket.emit('client_send_paste_key', {data: input.value});input.value = '';});// 绑定Enter键事件document.getElementById('enter_button').addEventListener('click', (e) => {socket.emit('client_send_enter_key');});// 绑定Delete键事件document.getElementById('delete_button').addEventListener('click', (e) => {socket.emit('client_send_delete_key');});});</script></head><body><div id="telescreen"><img id="remote_screen" src="" alt="远程屏幕"></div><div id="control_panel"><button id="get_screen">刷新远程屏幕</button><br/><input type="text" id="message_input" placeholder="输入要发送给远程屏幕的消息"><br/><button id="send_button">发送输入文本</button><br/><button id="paste_button">粘贴输入文本</button><button id="delete_button">Delete</button><br/><button id="enter_button">Enter</button></div></body></html>'''if __name__ == '__main__':socketio.run(app, debug=True,host='0.0.0.0',port=5000)

http://www.dtcms.com/a/441786.html

相关文章:

  • flask_socketio+pyautogui实现的具有加密传输功能的极简远程桌面
  • 深入了解linux网络—— TCP网络通信(上)
  • Android Jetpack 核心组件实战:ViewModel + LiveData + DataBinding 详解
  • 商务厅网站建设意见怎么做网站注册推广
  • Fragment 崩溃恢复后出现重叠问题的复现方式
  • 设计模式(C++)详解——策略模式(2)
  • 使客户能够大规模交付生产就绪的人工智能代理
  • Layui 前端和 PHP 后端的大视频分片上传方案
  • 无状态HTTP的“记忆”方案:Spring Boot中CookieSession全栈实战
  • Java 内存模型(JMM)面试清单(含超通俗生活案例与深度理解)
  • 2015网站建设专业建网站设计公司
  • vue+springboot项目部署到服务器
  • QT肝8天17--优化用户管理
  • QT肝8天19--Windows程序部署
  • 【开题答辩过程】以《基于 Spring Boot 的宠物应急救援系统设计与实现》为例,不会开题答辩的可以进来看看
  • 成都seo网站建设沈阳网站建设推广服务
  • 网站栏目名短链接在线生成官网免费
  • Task Schemas: 基于前沿认知的复杂推理任务架构
  • 第三十七章 ESP32S3 SPI_SDCARD 实验
  • 企业营销型网站特点企业信息查询系统官网山东省
  • docker-compose 安装MySQL8.0.39
  • Go语言入门(18)-指针(上)
  • Django ORM - 聚合查询
  • 【STM32项目开源】基于STM32的智能老人拐杖
  • YOLO入门教程(番外):卷积神经网络—汇聚层
  • 网站改版一般需要多久智慧团建学生登录入口
  • Dotnet接入AI通过Response创建一个简单控制台案例
  • 【论文笔记】2025年图像处理顶会论文
  • 用 Maven 配置 Flink 从初始化到可部署的完整实践
  • 做职业规划的网站seo学院