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)
相关推荐
bulucc13 小时前
一个简答的意图识别Agent
python·大模型·agent
Lizhihao_13 小时前
Python如何写Selenium全攻略
开发语言·python
m0_7381207214 小时前
网络安全编程——TCP客户端以及服务端Python实现
python·tcp/ip·安全·web安全·网络安全
AntBlack15 小时前
不当韭菜 : 好像真有点效果 ,想藏起来自己用了
前端·后端·python
百锦再15 小时前
破茧成蝶:全方位解析Java学习难点与征服之路
java·python·学习·struts·kafka·maven·intellij-idea
可触的未来,发芽的智生15 小时前
触摸未来2025-10-25:蓝图绘制
javascript·python·神经网络·程序人生·自然语言处理
新手村领路人16 小时前
python opencv gpu加速 cmake msvc cuda编译问题和设置
开发语言·python·opencv
暴风鱼划水17 小时前
卡码网语言基础课(Python) | 19.洗盘子
python·算法
Gitpchy17 小时前
Day 23 机器学习管道 pipeline
python·机器学习