形容
最近,使用节点实现了一个远程桌面监控应用程序,该应用程序分为服务器和客户端。客户端可以实时监控服务器的桌面,通过鼠标和键盘控制服务器的桌面。
这里,因为我用的是同一台电脑,监控屏幕是这样的。当然,使用两台计算机是有意义的,一台用于运行客户端,一台用于运行服务器。
原则
其实这个应用的功能主要分为两个部分。一是实现监控,即在客户端可以看到服务器的桌面。这部分功能是通过定时截图实现的。例如,服务器端每秒钟拍摄几次图片,然后通过socketio将其发送到客户端。客户端通过改变img的src,可以逐帧显示最新的图片,让其看到动态桌面。监控就是这样实现的。
另一个功能是控制,也就是客户端在监控屏幕上的操作,包括鼠标和键盘的操作,才能真正在服务器的桌面上生效。该功能的实现是为了监控电子应用中的所有鼠标和键盘事件,如按键、向上键、按键、向下键、向上键、移动键、点击键等。然后,事件通过socketio传输到服务器,服务器通过robot-js执行不同的事件,这样就可以在服务器上触发客户端事件。
实现
原理完成后,让我们具体实现(源代码链接在这里)。
实现套接字通信
首先,服务器和客户端分别引入socket.io和socket.io-client,并分别进行初始化
服务器端:
const app=new Koa();const server=http . CreateServer(app . callback());createSocketIO(服务器);app . use((CTX): void={ CTX . body='请连接使用插座';});server.listen(端口,(): void={ console.log '(服务器在http://localhost: '端口启动);});//createsocketiocconst io=socket io(服务器,{ pingInterval: 10000,pingTimeout: 5000,cookie : false });io.on('connect ',(socket): void={ socket . emit(' msg ',' connected ');}客户端:
varsocket=this . socket=io(' http://' this . IP ' :3000 ')socket . on(' msg ',(msg)={ console . log(msg)})socket . on(' error ',(err)={alert ('error ')
实施桌面监控
之后,我们必须首先在服务器端截图,并使用截图-桌面包
const截图=require('截图-桌面')const截图_ INTERVAL=500export const createsscreenshot=(): Promise[string,Buffer]={返回截图({format: 'png'})。然后((img): [string,Buffer]={ return[img . tostring(' base64 '),img];}).catch((err): { }={ console . log '(截图失败,err);返回错误;})} export const startScreenshotTimer=(回调): { }={ return setInterval((): void={ createsscreenshot()。然后(([imgStr,IMG]): void={ callback([' data : image/png;base64,' imgStr,IMg]);}) },SCOTT _ INTERVAL)}然后通过socketio的emit传输到客户端:
startScreenshotTimer(([imgStr,img]): void={ io . sockets . emit('截图',imgStr);});客户端收到图片后,设置为img的src(这里是base64的图片URL):
Img class='截图' : src=' http:截图'/data(){ return {截图:''}} socket.on('截图',(数据)={this。截图=数据})其实桌面监控已经实现了。感兴趣,
当然这个方案是有问题的,因为我们需要知道服务器桌面的大小,然后根据这个来调整客户端显示的图片大小。
为了实现这个细节,我们使用get-pixels库,它可以读取本地图片文件的宽度和高度等信息,所以我先把图片写在本地,然后读出,从而得到屏幕大小。
界面屏幕大小{宽度:数字高度:号;}函数getScreenSize(img):承诺screensize { const IMgpath=path。解决(过程。CWD(),' ./tmp。png ');fs.writeFileSync(imgPath,IMG);返回新的promise((resolve): void={ GetPixels(IMgpath,function(err,Pixels): void { if(err){ console。日志('坏图像路径')返回}分辨率({宽度:像素。形状[0],高度:像素。形状[1]});});})}然后通过socektio传递给客户端
getScreenSize(img).然后(({宽度,高度})={ io。插座。emit(' screensize ',{ width,height })});客户端收到之后调整图片大小就可以了
img class='截图' : src=' http :截图' : style='截图style '/data(){ return {截图: ' ',screenshotStyle: ' ',}}socket.on('screensize ',(screensize)={ this。截图样式={ ' width ' :屏幕大小。宽度' px ',高度' 3:屏幕大小。高度' px } })至此已经实现了桌面监控,并且图片尺寸和服务端屏幕的尺寸是一致的。
这里还有一个细节,就是获取到的图片大小是物理像素,而客户端设置的像素是设备无关像素,也就是要除以项目文件才是像素的值。这里需要获取dpr,因为目前只是在老兄下用,所以直接除以2了。
实现远程控制
代码写到这里,客户端的电子应用中已经可以实时显示服务端的桌面了。(当然像输入互联网协议(互联网协议的缩写)的弹框,以及电子真空和以打字打的文件等和主要逻辑无关的细节就不展开了。)
接下来我们要实现远程控制,也就是监听事件,传递事件,执行事件这几部分。
首先我们定义一下传递的事件的格式:
接口MouseEvent { type:字符串;按钮类型:字符串;x:号;y:号;}接口KeyboardEvent { type:字符串键码:号;keyName:字符串;}鼠标事件鼠标事件,类型为鼠标事件的类型,具体的值包括鼠标向下、鼠标向上、鼠标移动、点击、点击、按钮类型指的是鼠标的左键还是右键,值为左边的或对,x和y是具体的坐标。
键盘事件键盘事件,类型为键盘事件的类型,具体的值包括向下键、向上键、按键、键码为键盘码,keyName为键的名字。
接下来我们要在客户端监听事件:
图片类='屏幕截图: src=' http :截图' : style=' screenshotStyle ' @鼠标按下=' handleMouseEvent ' @ mousemove=' handleMouseEvent ' @ mouseup=' handleMouseEvent ' @ dblclick=' handleMouseEvent '/window。onkey press=window。onkey up=window。onkey down=这个。handlekeyboardevent通过socekt把事件传递到服务端
handleKeyboardEvent(e){ this。插上这个。插座。emit(' user event ',{ type: 'keyboard ',event: { type: e.type,keyName: e.key,keyCode: e.keyCode } }) },handleMouseEvent(e){ this。插上这个。插座。发出('用户事件',{ type: '鼠标',事件3: { type 3: e,type,buttonType:right' : 'left ',x: e.clientX,y: e.clientY } }) },然后在服务端把事件取出来执行,执行事件使用的是机器人-js:
const {鼠标、点、键盘}=require(' robot-js ');接口MouseEvent { type:字符串;按钮类型:字符串;x:号;y:号;}接口KeyboardEvent { type:字符串键码:号;keyName:字符串;}导出默认类事件执行器{公共鼠标公共键盘;公共构造函数(){这个。Mouse=new Mouse();这个。键盘=新键盘();} public execute KeyboardEvent(事件: KeyBoard event): void { switch(事件。type){ case ' keydown ' : this。键盘事件。按(事件。键码);打破;case ' key up ' :这个。键盘。发布(事件。键码);打破;case ' keypress ' :这个。键盘。点击(事件。键码);打破;default : break } } public executemousevent(事件): void { mouse。设定点(新点(事件。x,事件。y));const按钮=事件。按钮类型==='左侧'?0 : 2开关(事件。type){ case ' mouse down ' : this。老鼠。印刷机(按钮);打破;case ' mouse move ' : break case ' mouse up ' :这个。老鼠。释放(按钮);打破;案例'点击' :这个。老鼠。点击(按钮);打破;case ' dbl click ' :这个。老鼠。点击(按钮);this.mouse.click(按钮);打破;default : break } } public exec tue(EventInfo): void { console。日志(EventInfo);开关(EventInfo。type){ case ' keyboard ' : this。executeKeyboardevent(EventInfo。事件);打破;案例'鼠标' :这个。executemousevent(事件信息。事件);打破;default: break} }}至此,桌面监控和远程控制的客户端还有服务端的部分,以及两端的通信都已经实现了。思路其实并不麻烦,但细节还是很多的。有兴趣的同学可以把代码下下来跑跑试试,或者按着这个思路自己实现一遍,还是挺好玩的。
源码链接
远程监控服务器
远程监控客户端
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。