Python 手把手实现远程控制桌面


本项目旨在让大家理解远控软件的原理,通过远控桌面可以实现远程控制我们的电脑,更好更方便的管理电脑。文末将给出初始版的完整代码,需要使用到的其他工具也会有所说明。最终实现的效果就是只要用户点击了客户端的程序运行,我们就可以在服务端对其进行控制。效果如下:左边是客服端程序运行了,然后我们就可以在左边的另一台电脑上打开服务端程序进行控制,可以看到左边的屏幕图像也已经显示在了右边的电脑上。完整代码见文末!

1#客户端代码
2import?socket
3import?threading
4import?cv2
5import?numpy?as?np
6from?PIL?import?ImageGrab
7from?pynput.mouse?import?Button,Controller
1#接受服务器返回的数据的函数
2m?=?Controller()
3def?recvlink(client):
4????while?True:
5????????msg=client.recv(1024)
6????????msg=msg.decode('utf-8')
7????????print(msg)
8????????key?=?msg.split(",")
9????????xp?=?int(key[0])
10????????yp?=?int(key[1])
11????????m.position?=?((xp,yp))
12????????m.click(Button.left,1)
1#创建ipv4的socket对象,使用TCP协议(SOCK_STREAM)
2client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
3#设置服务器ip地址,注意应该是服务器的公网ip
4host='服务器的公网ip'
5#设置要发送到的服务器端口,需要在云服务器管理界面打开对应端口的防火墙
6port=设置的端口
7#建立TCP协议连接,这时候服务器就会监听到到连接请求,并开始等待接受client发送的数据
8client.connect((host,port))
9#建立连接后,服务器端会返回连接成功消息
10start_msg=client.recv(1024)
11print(start_msg.decode('utf-8'))
12#开启一个线程用来接受服务器发来的消息
13t=threading.Thread(target=recvlink,args=(client,))
14t.start()
15p?=?ImageGrab.grab()#获得当前屏幕
16quality?=?25??#?图像的质量
17encode_param?=?[int(cv2.IMWRITE_JPEG_QUALITY),?quality]
18while?True:
19????im?=?ImageGrab.grab()
20????imm=cv2.cvtColor(np.array(im),?cv2.COLOR_RGB2BGR)#转为opencv的BGR格式
21????imm?=?cv2.resize(imm,?(1535,?863))
22????img_encode?=?cv2.imencode(".jpg",?imm,?encode_param)[1]
23????data_encode?=?np.array(img_encode)
24????str_encode?=?data_encode.tostring()
25????#print(len(str_encode))
26????#输入要发送的信息
27????sendmsg="kehu"
28????#向服务器发送消息
29????client.send(str_encode)
30????if?sendmsg=='quit':
31????????break
32#结束时关闭客户端
33client.close()
1#服务器端
2import?socket
3import?threading
4import?numpy?as?np
5import?cv2
6import?os
1print("等待连接---")
2def?mouse_click(event,?x,?y,?flags,?para):
3????if?event?==?cv2.EVENT_LBUTTONDOWN:??#?左边鼠标点击
4????????f=open("1.txt","w")
5????????f.write(str(x)+","+str(y))
6????????f.close()
1def?recv_msg(clientsocket):
2????while?True:
3????????#?接受客户端消息,设置一次最多接受10240字节的数据
4????????recv_msg?=?clientsocket.recv(102400)
5????????#?把接收到的东西解码
6????????msg?=?np.fromstring(recv_msg,?np.uint8)
7????????img_decode?=?cv2.imdecode(msg,?cv2.IMREAD_COLOR)
8????????try:
9????????????s=img_decode.shape
10????????????img_decode=img_decode
11????????????temp=img_decode
12????????except:
13????????????img_decode=temp
14????????????pass
15????????cv2.imshow('SERVER',?img_decode)
16????????cv2.setMouseCallback("SERVER",?mouse_click)
17????????try:
18????????????f=open("1.txt")
19????????????txt=f.read()
20????????????f.close()
21????????????reply=txt
22????????????print(reply)
23????????????clientsocket.send(reply.encode('utf-8'))
24????????????os.remove("1.txt")
25????????except:
26????????????pass
27????????if?cv2.waitKey(1)?&?0xFF?==?ord('q'):
28????????????break
1def?main():
2????socket_server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
3????host='服务器的本地ip'
4????#设置被监听的端口号,小于1024的端口号不能使用
5????port=设置的端口
6????socket_server.bind((host,port))
7????#设置最大监听数,也就是最多可以同时响应几个客户端请求,一般配合多线程使用
8????socket_server.listen(5)
9????#等待客户端连接,一旦有了连接就立刻向下执行,否则等待
10????#accept()函数会返回一个元组,第一个元素是客户端socket对象,第二个元素是客户端地址(ip地址+端口号)
11????clientsocket,addr=socket_server.accept()
12????#?有了客户端连接后之后才能执行以下代码,我们先向客户端发送连接成功消息
13????clientsocket.send('连接成功'.encode('utf-8'))
14????#?和客户端一样开启一个线程接受客户端的信息
15????t=threading.Thread(target=recv_msg,args=(clientsocket,))
16????t.start()


1from?PyQt5.QtWidgets?import?*
2from?PyQt5.QtCore?import?*
3from?PyQt5.QtGui?import?QPalette,?QBrush,?QPixmap
4import?os
5import?socket
6import?threading
7import?cv2
8import?numpy?as?np
9from?PIL?import?ImageGrab
10from?pynput.mouse?import?Button,Controller
11import?time
1m?=?Controller()
2def?mouse_click(event,?x,?y,?flags,?para):
3????if?event?==?cv2.EVENT_LBUTTONDOWN:??#?左边鼠标点击
4????????print(?x,?y)
5????????m.position?=?(x,?y)
6????????time.sleep(0.1)
7????????m.click(Button.left,?1)
1def?__init__(self,?parent=None):
2????super(Ui_MainWindow,?self).__init__(parent)
3????#?self.face_recong?=?face.Recognition()
4????self.timer_camera?=?QtCore.QTimer()
5????self.cap?=?cv2.VideoCapture()
6????self.CAM_NUM?=?0
7????self.set_ui()
8????self.slot_init()
9????self.__flag_work?=?0
10????self.x?=?0
11????self.count?=?0
1def?set_ui(self):
2????self.__layout_main?=?QtWidgets.QHBoxLayout()
3????self.__layout_fun_button?=?QtWidgets.QVBoxLayout()
4????self.__layout_data_show?=?QtWidgets.QVBoxLayout()
5????self.button_open_camera?=?QtWidgets.QPushButton(u'远程桌面')
6????self.button_close?=?QtWidgets.QPushButton(u'退出')
7????#?Button?的颜色修改
8????button_color?=?[self.button_open_camera,?self.button_close]
9????for?i?in?range(2):
10????????button_color[i].setStyleSheet("QPushButton{color:black}"
11??????????????????????????????????????"QPushButton:hover{color:red}"
12??????????????????????????????????????"QPushButton{background-color:rgb(78,255,255)}"
13??????????????????????????????????????"QPushButton{border:2px}"
14??????????????????????????????????????"QPushButton{border-radius:10px}"
15??????????????????????????????????????"QPushButton{padding:2px?4px}")
16????self.button_open_camera.setMinimumHeight(50)
17????self.button_close.setMinimumHeight(50)
18????# move()方法移动窗口在屏幕上的位置到x = 300,y = 300坐标。
19????self.move(500,?500)
20????#?信息显示
21????self.label_show_camera?=?QtWidgets.QLabel()
22????self.label_move?=?QtWidgets.QLabel()
23????self.label_move.setFixedSize(100,?100)
24????self.label_show_camera.setFixedSize(1530,863)
25????self.label_show_camera.setAutoFillBackground(False)
26????self.__layout_fun_button.addWidget(self.button_open_camera)
27????self.__layout_fun_button.addWidget(self.button_close)
28????self.__layout_fun_button.addWidget(self.label_move)
29????self.__layout_main.addLayout(self.__layout_fun_button)
30????self.__layout_main.addWidget(self.label_show_camera)
31????self.setLayout(self.__layout_main)
32????self.label_move.raise_()
33????self.setWindowTitle(u'远控桌面GUI')
34????'''
35????#?设置背景图片
36????palette1?=?QPalette()
37????palette1.setBrush(self.backgroundRole(),?QBrush(QPixmap('background.jpg')))
38????self.setPalette(palette1)
39????'''
1def?mousePressEvent(self,event):
2????if?event.buttons()?&?QtCore.Qt.LeftButton:
3????????x?=?event.x()-120
4????????y?=?event.y()-10
5????????text?=?"x:?{0},y:?{1}".format(x,y)
6????????if?x>=0?and?y>=0:
7????????????m.position?=?(x,?y)
8????????????time.sleep(0.1)
9????????????m.click(Button.left,?1)
10????????print(text)
1def?slot_init(self):
2????self.button_open_camera.clicked.connect(self.button_open_camera_click)
3????self.timer_camera.timeout.connect(self.show_camera)
4????self.button_close.clicked.connect(self.close)
1def?button_open_camera_click(self):
2????if?self.timer_camera.isActive()?==?False:
3????????self.timer_camera.start(30)
4????????self.button_open_camera.setText(u'关闭')
5????else:
6????????self.timer_camera.stop()
7????????self.cap.release()
8????????self.label_show_camera.clear()
9????????self.button_open_camera.setText(u'远程桌面')
1def?show_camera(self):
2????im?=?ImageGrab.grab()
3????imm?=?cv2.cvtColor(np.array(im),?cv2.COLOR_RGB2BGR)??#?转为opencv的BGR格式
4????#imm?=?cv2.resize(imm,?(1535,?863))
5????self.image?=?imm
6????#?face?=?self.face_detect.align(self.image)
7????#?if?face:
8????#?????pass
9????show?=cv2.resize(self.image,?(1536,863))
10????show?=?cv2.cvtColor(show,?cv2.COLOR_BGR2RGB)
11????print(show.shape[1],?show.shape[0])
12????#?show.shape[1]?=?640,?show.shape[0]?=?480
13????showImage?=?QtGui.QImage(show.data,?show.shape[1],?show.shape[0],?QtGui.QImage.Format_RGB888)
14????self.label_show_camera.setPixmap(QtGui.QPixmap.fromImage(showImage))
15????#cv2.setMouseCallback(showImage,?mouse_click)
16????#?self.x?+=?1
17????#?self.label_move.move(self.x,100)
18????#?if?self.x?==320:
19????#?????self.label_show_camera.raise_()
20def?closeEvent(self,?event):
21????ok?=?QtWidgets.QPushButton()
22????cacel?=?QtWidgets.QPushButton()
23????msg?=?QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning,?u"关闭",?u"是否关闭!")
24????msg.addButton(ok,?QtWidgets.QMessageBox.ActionRole)
25????msg.addButton(cacel,?QtWidgets.QMessageBox.RejectRole)
26????ok.setText(u'确定')
27????cacel.setText(u'取消')
28????#?msg.setDetailedText('sdfsdff')
29????if?msg.exec_()?==?QtWidgets.QMessageBox.RejectRole:
30????????event.ignore()
31????else:
32????????#?????????????self.socket_client.send_command(self.socket_client.current_user_command)
33????????if?self.cap.isOpened():
34????????????self.cap.release()
35????????if?self.timer_camera.isActive():
36????????????self.timer_camera.stop()
37????????event.accept()


?腾讯回应两块八卖《鬼谷八荒》:已下架并退款;iMac Pro 售完即停产;iCloud 识别姓氏闹乌龙 | 极客头条
关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号随时掌握互联网精彩
赞助链接
排名
热点
搜索指数
- 1 打好关键核心技术攻坚战 7904332
- 2 在南海坠毁的2架美国军机已被捞出 7809623
- 3 立陶宛进入紧急状态 卢卡申科发声 7714273
- 4 持续巩固增强经济回升向好态势 7618661
- 5 多家店铺水银体温计售空 7520308
- 6 奶奶自爷爷去世9个月后变化 7426403
- 7 仅退款225个快递女子已归案 7329194
- 8 日舰曾收到中方提示 7237968
- 9 琉球归属问题被迫无限期搁置 7138997
- 10 我国成功发射遥感四十七号卫星 7048326








CSDN
