使用python和C混合编程实现远程控制(*****)
\关于图像编码问题**
\1**
我屏幕分辨率是 1920 1080 3 = 6220800,所每帧是 6220800/1024/1024 = 5.9M
如果 要60fps的话 则需要每秒传输 5.9M*60 = 360M/s 太大了 明显不可能
所以需要个图片压缩传输
\2**
如果用png压缩的话 是102K 如果60fps的话 则6m/S
也有点大
\3**
我们其实不行呀传送整张图片
我们只需要传送 这帧和上帧的差异部分就可以,这样就可以让传输变得更加快捷
png (im2 - im1)
所以我们选择 numpy 实现两张图片之间做一个减法
而opencv-python可以把两张图片的差 变成图片进行传输
Server:
\实现桌面的传输**
\1、对于被控端(server):**
具体步骤:
1、先建立一个套接字
2、实现桌面的截图
3、传输,接受控制端发的信息
4、实现 键盘和鼠标的操作
\、对于 控制端(client):**
具体步骤:
1、建立对应的套接字
2、收到数据流
3、根据套接字编码 而解码,并且监听自己cavas 鼠标 键盘 数据流 且发送给 server
4、通过从cv2.imshow() 进行show
具体的编码:
这里使用了 tkinter 模块 设置了IP地址 port 和大小等参数 实现了鼠标键盘的交互
并且
Client和server 通过并发编程来实现 图形的帧传输
也就是传输视频
以下是代码:
注意 这里我使用了 struct模块封装 图片 让其成为bytes流
再使用了canvas来show 图片
并且在 while ture:
下 ims = cv2.imdecode(data, cv2.IMREAD_COLOR)
img = img + ims
imt = cv2.resize(img, (w, h))
imsh = cv2.cvtColor(imt, cv2.COLOR_RGB2RGBA)
imi = Image.fromarray(imsh)
imgTK.paste(imi)
来实现了 一直 img.tk.paste
说白了就是只要有新图片传输了 解包了 就在canvas上面展示 这个图片
于是 实现了 图片的快速替换
也就是实现了视频的传输
这是在本机的效果:
明显 成功了
C语言编程:
Server.C :
Client.C:
使用了传统的套接字,重点就是 我们使用python中的ctypes库 实现了C和python传输
这里我们在linux用 GCC -FPIC -shared server.c -o server.so
把server和client都变成.so文件 也就是linux中的动态链接库
然后我们用server_C.py,client_C.py调用 其中的server.c和client.c
其中 server_C.py和client_C.py的函数体是一样的
都是对其中的调用
而 cdll.loadlibrary 函数 则指定了这两个函数库
其中 listenfd server_listenfd 等都是 c_int类型 与C语言模块中socket 中类型一样
这两个 则是 c_char_p 类型 在C语言对应了 改变的bufsize
以下转换就不一一概述了
这是server_c .py 实现了talk
我使用了python中threading模块 start它 实现了传输和接送的并发
Client 同理
代码类似
接下来我们把目光 放到主要的远程控制文件中 在
上面的论述中我们实现了 图形界面的传输
接下来我们要实现 键盘和鼠标 传输和操作
首先是控制端:
我们把tinker模块的canvas 中bind (sequence =”?”,func = ?)这个模块 来 封装
其中sequence 代表的是 键盘事件
其中int参数e代表着 e在canvas中的像素位置
1 是左键 2是右键 如此类推
Func 则对应了此事件发生时引发的函数
这里 我们先封装了 conn 也就是套接字
Eventdo 则是用conn链接的套接字发送其中的信息
其他函数 则是直接发送 e.x/scale 也就是放缩比
得到的值就是 在控制端 鼠标应该出现的位置
左键 右键 滚轮 同理
然后我们在被控端
接受这些鼠标和键盘的数据流
Socket 套接字部分就不说了和 上述图形传输一样
这里我使用了python中
来实现鼠标和键盘 的操作
(然后我就发现了一个问题)
在linux 和 windows中 中 python的keyboard对应的值是不同的
于是我在github中
找到了 所有平台对用的keyboard值 并且把他 独立出来 成为一个模块
Github 链接:https://github.com/boppreh/keyboard/tree/master/keyboard
也就是keyboard.py :
就这样我知道了 linux 平台是 X11
这些就是所有平台的 keycode
于是我又回头在 控制端 设置了平台函数
为了就是 实现 平台中key不错误
解决了keycode问题
我就实现了
鼠标和键盘 的按下和弹起操作
到目前为止
我的代码已经完成
当我到虚拟机实验时不出意外的报错了
错误信息是:
和
之后我在github上面找到了解决方案:
解决方案链接: https://github.com/python-pillow/Pillow/issues/5130
下面的解决方案则是 python中 xdisplay要和linux中的echo $display 参数一样
我估计 :0在Ubuntu中是wayland :1才是 X
其中我才发现了 unbuntu 居然没用X 而是使用了 wayland
还好找到了这个解决问题的方案 不然就寄了
发现我可以在linux 127.0.0.1 传输视频了
当我在两个虚拟机中传输时 又出现了问题:
X connection failed: error 1
后来我通过谷歌 终于发现了解决方法
原来 X 在进行链接的时候要先host+一下 我真是醉了
于是在linux 中输入Xhost + 开启所有链接
然后再次实验
终于成功了
这是 两个虚拟机 右面是被控端 找到ip地址
然后写入 点击show
成功控制
字符串传输成功
成功实现了 远程控制
实验总结:
这次实验我收获非常大
C和python的混合编程
如何图像传输
对C和python中套接字的 理解更上一层 没想到 python的socket和C的socket完全不同 尤其是 C中居然还有个自己的类型
然后就是感谢 下github上那些解决问题的人 没有他们我估计是肯定没法发现这Ubuntu还花活 总而言之 这次收获非常之大
Ps:
我之前曾经实现过 一个反木马 可以用shell操作来实现对于肉鸡的控制 但是总归还是不如 远程链接的控制 来的易操作和获得权限
在我学习 yolo的时候 由于这个小电脑 不能进行跑cuda 于是我把自己的游戏本 放在宿舍 通过 向日葵这个 来实现远程控制 让自己的游戏本跑 深度学习
之后我就想 我能不能自己写一个 远程控制呢? 还是跨平台的 (向日葵不支持 linux)。
然后感谢 bilibili上面 pysrc大佬,我是向这个大佬是学习 实现了远程链接