当前位置:   article > 正文

自己动手实现网页版的远程桌面_网页版windows远程桌面

网页版windows远程桌面

背景

因为一些原因,小编需要使用远程桌面软件,但小编实在穷,所以使用的是免费版的向日葵。就在前几天,免费版的向日葵莫名其妙崩了(各种重启都没用),虽然之后通过升级这种高级手段又重新可以用了,但是这在我幼小的心灵上留下了创伤,所以,我决定自己手写一个远程桌面WEB版。不过最后因为时间有限,我写了个demo出来,以后有时间再完善吧。这次,我把自己的思路放出来供大家参考。

实现原理

截取当前屏幕,并通过websocket将其发到Web端展示,Web端编写鼠标、键盘事件,通过WebSocket发送到服务端处理。

服务端

服务端使用了WPF进行开发,websocket用了第三方库WebSocketSharpFork来实现。

接下来,上代码:

WebSocket处理数据

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WebSocketSharp;
using WebSocketSharp.Server;

namespace RemoteApp
{
    public class Echo : WebSocketBehavior
    {
        private bool isClose = false;

        protected override void OnClose(CloseEventArgs e)
        {
            isClose = true;
            Trace.WriteLine("Closed...");
        }

        protected override void OnMessage(MessageEventArgs e)
        {
            Trace.WriteLine(e.Data);
            HandleData(e.Data);
        }

        protected override void OnOpen()
        {
            Trace.WriteLine("Open...");
            //Sessions.Broadcast("Open...");

            Thread thread = new Thread(UpdateDesktop);
            thread.Start();
        }

        private void UpdateDesktop()
        {
            while (true)
            {
                if (isClose) return;
                Bitmap bitmap = GetBitmapFromScreen();
                Sessions.Broadcast(BitmapToByte(bitmap));
            }
        }

        private void HandleData(string data)
        {
            try
            {
                JObject item = (JObject)JsonConvert.DeserializeObject(data);
                int type = Int32.Parse(item["type"].ToString());
                byte keyCode;
                int x, y;
                switch (type)
                {
                    // Key Down
                    case 0:
                        keyCode = byte.Parse(item["key"].ToString());
                        KeyBoard.keyDown(keyCode);
                        break;
                    // Key Up
                    case 1:
                        keyCode = byte.Parse(item["key"].ToString());
                        KeyBoard.keyUp(keyCode);
                        break;
                    // Mouse move
                    case 2:
                        x = Convert.ToInt32(Convert.ToDouble(item["x"].ToString()));
                        y = Convert.ToInt32(Convert.ToDouble(item["y"].ToString()));
                        MouseFlag.SetCursorPos(x, y);
                        break;
                    // Mouse Left Click
                    case 3:
                        x = Convert.ToInt32(Convert.ToDouble(item["x"].ToString()));
                        y = Convert.ToInt32(Convert.ToDouble(item["y"].ToString()));
                        MouseFlag.MouseLeftClickEvent(x, y, 0);
                        break;
                    // Mouse Right Click
                    case 4:
                        x = Convert.ToInt32(Convert.ToDouble(item["x"].ToString()));
                        y = Convert.ToInt32(Convert.ToDouble(item["y"].ToString()));
                        MouseFlag.MouseRightClickEvent(x, y, 0);
                        break;
                    // Mouse Left Down
                    case 5:
                        x = Convert.ToInt32(Convert.ToDouble(item["x"].ToString()));
                        y = Convert.ToInt32(Convert.ToDouble(item["y"].ToString()));
                        MouseFlag.MouseLeftDownEvent(x, y, 0);
                        break;
                    // Mouse Left Up
                    case 6:
                        x = Convert.ToInt32(Convert.ToDouble(item["x"].ToString()));
                        y = Convert.ToInt32(Convert.ToDouble(item["y"].ToString()));
                        MouseFlag.MouseLeftUpEvent(x, y, 0);
                        break;
                    // Mouse Wheel
                    case 7:
                        x = Convert.ToInt32(Convert.ToDouble(item["x"].ToString()));
                        y = Convert.ToInt32(Convert.ToDouble(item["y"].ToString()));
                        var d = Convert.ToInt32(Convert.ToDouble(item["deltaY"].ToString())) * Convert.ToInt32(Convert.ToDouble(item["deltaFactor"].ToString()));
                        MouseFlag.MouseWheelEvent(x, y, d);
                        break;

                }
            }
            catch(Exception e)
            {

            }
        }

        private Bitmap GetBitmapFromScreen()
        {

            System.Drawing.Rectangle rc = System.Windows.Forms.SystemInformation.VirtualScreen;
            var bitmap = new Bitmap(rc.Width, rc.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(bitmap))
            {
                g.CopyFromScreen(rc.X, rc.Y, 0, 0, rc.Size, System.Drawing.CopyPixelOperation.SourceCopy);
            }

            return bitmap;
        }

        private Byte[] BitmapToByte(Bitmap bitmap)
        {
            MemoryStream stream = new MemoryStream();
            bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
            Byte[] buffer = new Byte[stream.Length];
            stream.Seek(0, SeekOrigin.Begin);
            stream.Read(buffer, 0, Convert.ToInt32(stream.Length));
            return buffer;
        }

    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144

开启WebSocket

private void OpenWebSocketServer()
{
    server = new WebSocketServer(int.Parse(PortName.Text));

    server.AddWebSocketService<Echo>("/Echo");
    server.Start();

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

客户端

Web端随便用了HTML写了一下,大家参考一下就行

<html>
    <head>
        <title>Remote</title>
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery-mousewheel/3.1.9/jquery.mousewheel.min.js"></script>
    </head>
    <script>
         	var ws;
            var isEnter = false;
            var remoteWidth = 1920;
            var remoteHeight = 1080;
            var widthRadio = remoteWidth / 1000;
            var heightRadio = remoteHeight / 600;

            function OpenWS() {
                initWS();
                initEvent();
            }

            function initWS() {
                ws = new WebSocket("ws://192.168.1.105:10086/Echo");
                ws.onopen = function () {
                    console.log("Openened connection to websocket");

                };
                ws.onclose = function () {
                    console.log("Close connection to websocket");
                    
                    // 断线重连
                    initWS();
                }

                ws.onmessage = function (e) {
                    // console.log(e.data)
                    var blob = new Blob([e.data], { type: "image/jpg" });
                    var url = URL.createObjectURL(blob);
                    var image = document.getElementById("desktop");
                    image.src = url;
                }
            }

            function initEvent(){

                //禁用文本选择
                document.onselectstart = function(e){
                    e = window.event || e;
                    if(window.event){
                        try{e.keyCode = 0;}catch(e){}
                        e.returnValue = false;
                    }else{
                        e.preventDefault();
                    }
                };
                
                //禁用右键菜单
                $(document).contextmenu(function(e){
                    e = window.event || e;

                    if(isEnter)
                        sendRightClick(e.offsetX * widthRadio, e.offsetY * heightRadio, 1);

                    if(window.event){
                        try{e.keyCode = 0;}catch(e){}
                        e.returnValue = false;
                    }else{
                        e.preventDefault();
                    }
                });

                $(document).keydown(function (e) {
                    e = window.event || e;
                    var keycode = e.keyCode || e.which
                    // console.log('Down' + e.keyCode);
                    if(isEnter)
                        sendKeyDown(keycode);
                    if(e.ctrlKey || e.altKey || e.shiftKey || (keycode > 111 && keycode <124)){
                        if(window.event){
                            try{e.keyCode = 0;}catch(e){}
                            e.returnValue = false;
                        }else{
                            e.preventDefault();
                        }
                        // window.event.returnValue = false;
                    }

                });

                $(document).keyup(function(e) {
                    var keycode = e.keyCode || e.which
                    // console.log('up' + e.keyCode);
                    if(isEnter)
                        sendKeyUp(keycode)
                });

                $(document).mousemove(function(e) {
                    if(isEnter)
                        sendMouseMove(e.offsetX * widthRadio, e.offsetY * heightRadio);
                });

                $(document).click(function(e) { 
                    console.log('click');
                    if(isEnter)
                        sendLeftClick(e.offsetX * widthRadio, e.offsetY * heightRadio);
                });

                $(document).mousedown(function(e){
                    // console.log('mouse down');
                    if(isEnter)
                    sendMouseLeftDown(e.offsetX * widthRadio, e.offsetY * heightRadio);
                });

                $(document).mouseup(function(e) {
                    // console.log('mouse up');
                    if(isEnter)
                        sendMouseLeftUp(e.offsetX * widthRadio, e.offsetY * heightRadio);
                });

                $(window).mousewheel(function(e) {
                    // console.log(e);
                    sendMouseWheel(e.offsetX * widthRadio, e.offsetY * heightRadio, e.deltaY, e.deltaFactor);
                });
                
            }

            function sendKeyDown(keyCode){
                ws.send("{'type':0, 'key':" + keyCode + "}")
            }
            
            function sendKeyUp(keyCode){
                ws.send("{'type':1, 'key':" + keyCode + "}")
            }

            function sendMouseMove(dx, dy){
                ws.send("{'type':2, 'x':" + dx + ", 'y':" + dy +"}");
            }

            function sendLeftClick(dx, dy){
                ws.send("{'type':3, 'x':" + dx + ", 'y':" + dy + "}");
            }
            
            function sendRightClick(dx, dy){
                ws.send("{'type':4, 'x':" + dx + ", 'y':" + dy + "}");
            }

            function sendMouseLeftDown(dx, dy){
                ws.send("{'type':5, 'x':" + dx + ", 'y':" + dy + "}");
            }
            
            function sendMouseLeftUp(dx, dy){
                ws.send("{'type':6, 'x':" + dx + ", 'y':" + dy + "}");
            }

            function sendMouseWheel(dx, dy, deltaY, deltaFactor) {
                ws.send("{'type':7, 'x':" + dx + ", 'y':" + dy + ", 'deltaY':" + deltaY + ", 'deltaFactor':" + deltaFactor + "}");

            }

            function imgMouseEnter(){
                isEnter = true;
            }

            function imgMouseLeave(){
                isEnter = false;
            }

    </script>
    <body>
        <button onclick="OpenWS()">打开WebSocket</button>
        <img id="desktop" width="1000" height="600" draggable="false" onmouseenter="imgMouseEnter()" onmouseleave="imgMouseLeave()"/>
    </body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171

展示图片

服务端界面

服务端界面

Web端界面

Web端界面

最后

界面随便写写的,代码我放GitHub上了,有兴趣的自己去看
代码:远程桌面Web版

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/161449
推荐阅读
相关标签
  

闽ICP备14008679号