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

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

python 复制代码
import base64
import pyautogui
from flask import Flask
import time
from flask_socketio import SocketIO, emit
from io import BytesIO
import pyperclip


app=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)
相关推荐
东方芷兰3 小时前
LLM 笔记 —— 02 大语言模型能力评定
人工智能·笔记·python·神经网络·语言模型·自然语言处理·cnn
羞儿3 小时前
【pytorch】数据增强与时俱进,未来的改进和功能将仅添加到 torchvision.transforms.v2 转换中
pytorch·python·深度学习·数据增强
可触的未来,发芽的智生4 小时前
新奇特:负权重橡皮擦,让神经网络学会主动遗忘
人工智能·python·神经网络·算法·架构
咖啡Beans4 小时前
Python常用系统自带库之json解析
python
付玉祥4 小时前
第 6 章 异常处理与文件操作
python
AI原吾5 小时前
ClaudeCode真经第二章:核心功能深度解析
python·ai编程·claudecode
东方芷兰5 小时前
LLM 笔记 —— 03 大语言模型安全性评定
人工智能·笔记·python·语言模型·自然语言处理·nlp·gpt-3
MediaTea5 小时前
Python 库手册:keyword 关键字查询
开发语言·python
java1234_小锋5 小时前
Scikit-learn Python机器学习 - 模型保存及加载
python·机器学习·scikit-learn