赞
踩
因为一些原因,小编需要使用远程桌面软件,但小编实在穷,所以使用的是免费版的向日葵。就在前几天,免费版的向日葵莫名其妙崩了(各种重启都没用),虽然之后通过升级这种高级手段又重新可以用了,但是这在我幼小的心灵上留下了创伤,所以,我决定自己手写一个远程桌面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; } } }
开启WebSocket
private void OpenWebSocketServer()
{
server = new WebSocketServer(int.Parse(PortName.Text));
server.AddWebSocketService<Echo>("/Echo");
server.Start();
}
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>
界面随便写写的,代码我放GitHub上了,有兴趣的自己去看
代码:远程桌面Web版
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。