最近想在游戏里挂脚本,需要通过VNC远程操控虚拟机桌面(主要是截图,键盘和鼠标事件),Python中的VNC库(asyncvnc、pyVNC、vncdotool)尝试了一轮都没有找到满意的,于是决定手搓一个
实现过程
起初是没什么头绪的,后面发现可以用WireShark网络抓包现有的VNC客户端,我这里尝试了MobaXTerm里的VNC Session和VNCViewer,都能在本地回环里抓包并分析,再用Socket套接字尝试着发包。
协议本身的内容还是比较简单的,从TCP三次握手建立连接,到Client和Server俩轮互发确认VNC版本和安全协议,接着Client发送Desktop Share Flag后,Server就会返回图像信息和桌面名称,后续就可以开始图像交互了
VNC底层的图像通信是RFB(Remote Frame Buffer),即缓冲帧。在发送更新帧请求后,每帧只会把与上一帧有区别的图像部分截取成一个个小的Rectangle发过来,这样有利于减少流量传输,并且会在头几个字节标明 (x,y,width,height) 和 BufferLength。如果是Raw的图像编码,根据长宽算好字节数接收进来转换为M*N*4的Array就可以作为图像使用了,需要注意的是默认的通道排列是BGRA,并且A为0,需要修改
键盘和鼠标事件也都是按照协议来的,目前还没对按键字段进行封装,后面有空再做
代码仓库
代码已在github上开源,下面是仓库地址
ForgetMelody/SocketVNC: A Simple VNC Client API implement by Socket (Python) (github.com)