网易首页 > 网易号 > 正文 申请入驻

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

0
分享至

  作者 | 李秋键

  责编 | 寇雪芹

  头图 | 下载于视觉中国

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

  远控流程

  1.1 环境要求

  本次环境使用的是python3.6.5+windows平台

  主要用的库有:图像处理库opencv,包括用来目标检测和图像处理等操作。

  Socket用来远程传输数据达到远程控制的效果;

  Threading模块用来创建多线程管理;

  Numpy模块用来辅助opencv对图像进行一些像素值操作;

  PIL模块用来获取屏幕图像数据;

  pynput.mouse用来控制鼠标点击事件。达到远程控制鼠标的作用。

  1.2 客户端讲解

  客户端在这里指的是被控制的电脑,就是我们需要受到控制的电脑。

  (1)首先是导入相关模块:

  1 #客户端代码
2 import socket
3 import threading
4 import cv2
5 import numpy as np
6 from PIL import ImageGrab
7 from pynput.mouse import Button,Controller

  (2)接着创建一个鼠标控制器和用来接收服务端数据的函数。因为需要一直都接收数据,故需要嵌入循环。在这里客户端还需要接收数据的原因是,用来接收服务端传来的鼠标控制信息,要不然怎么实现鼠标控制桌面的效果呢。

  1 #接受服务器返回的数据的函数
2m = Controller()
3 def 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)

  (3)创建ipv4的socket对象,使用TCP协议(SOCK_STREAM)。然后设置服务端IP地址,以及端口。这里用来向服务端传输数据,即传输桌面图像数据。注释代码如下:

  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.3 服务端讲解

  服务端指的是用来控制远程电脑的那一端,为了方便使用,我们直接在服务器上使用即可。

  (1)导入使用到的模块:

  1 #服务器端
2 import socket
3 import threading
4 import numpy as np
5 import cv2
6 import os

  (2)创建鼠标点击事件函数,用来获取鼠标点击的位置坐标:

  1print( "等待连接---")
2 def 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()

  (3)创建服务器端接收数据函数,用来实时接收传输过来的图像数据并显示:

  1 def 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

  (4)主函数,用来建立连接和数据接收等功能。

  1 def 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()

  远程控制GUI窗口

  远控桌面GUI主要是为了美观而用,需要大家根据远程代码进行集合修改。当然单独使用上述代码已经可以实现功能了,只是不够美观。由于考虑到此处代码量较大,且不是重点,故粗略讲解

  (1)导入相关库:

  1 from PyQt5.QtWidgets import *
2 from PyQt5.QtCore import *
3 from PyQt5.QtGui import QPalette, QBrush, QPixmap
4 import os
5 import socket
6 import threading
7 import cv2
8 import numpy as np
9 from PIL import ImageGrab
10 from pynput.mouse import Button,Controller
11 import time

  (2)建立鼠标控制函数和点击函数

  1m = Controller()
2 def 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)

  (3)GUI界面初始化,由于我们需要把实时的视频显示在窗口上,故也需要使用到opencv。

  1 def __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

  (4)设置窗口大小和控件位置等信息。创建布局和设置名称

  1 def 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 '''

  (5)获取鼠标点击时的坐标:

  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)

  (6)按钮绑定所设置的函数:

  1 def 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)

  (7)显示桌面功能函数,并设置点击时修改名称,可以随时关闭桌面

  1 def 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'远程桌面')

  (8)显示桌面函数和退出程序函数

  1 def 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_()
20 def 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()

  作者简介:李秋键,CSDN博客专家,CSDN达人课作者。硕士在读于中国矿业大学,开发有taptap竞赛获奖等。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
解读|M1和M2同比增速为何持续下行

解读|M1和M2同比增速为何持续下行

澎湃新闻
2024-06-15 07:24:26
世界女排联赛最新积分榜:日本超世界第1!全队又哭了!垫底队胜

世界女排联赛最新积分榜:日本超世界第1!全队又哭了!垫底队胜

求球不落谛
2024-06-15 20:24:24
日本“马赛克破解版”电影疯传,IT记者:在中国市场非常大

日本“马赛克破解版”电影疯传,IT记者:在中国市场非常大

葫芦哥爱吐槽
2024-06-14 09:31:50
退休金待遇比较高的人,一般都是什么类型的人呢?

退休金待遇比较高的人,一般都是什么类型的人呢?

社保小达人
2024-06-08 12:57:46
如果你背了很多负债,惨到亲人也瞧不起你,请牢记“卖驴”思维

如果你背了很多负债,惨到亲人也瞧不起你,请牢记“卖驴”思维

阿胖读书
2024-06-08 17:10:34
有人已经中招!你以为铁头施肥就完了?带来的影响逐步显现

有人已经中招!你以为铁头施肥就完了?带来的影响逐步显现

据说说娱乐
2024-06-15 16:49:23
路易小王子在庆典上表情包又火了!差点抢了凯特风头,还打哈欠呢

路易小王子在庆典上表情包又火了!差点抢了凯特风头,还打哈欠呢

童童聊娱乐啊
2024-06-15 23:14:36
他刚当市长就被老百姓指责,后来官至政治局常委,如今已经86岁了

他刚当市长就被老百姓指责,后来官至政治局常委,如今已经86岁了

李姐历史
2024-06-14 09:57:42
拜登已签字,22国一致对华征税,中方加量囤粮食,瑞典的努力白费

拜登已签字,22国一致对华征税,中方加量囤粮食,瑞典的努力白费

小小包工头阿汾
2024-06-15 17:11:37
金砖运动会金牌榜:中国队第三,以色列巴勒斯坦挂0,日本队垫底

金砖运动会金牌榜:中国队第三,以色列巴勒斯坦挂0,日本队垫底

小豆豆赛事
2024-06-15 18:08:35
青岛下跌7.3%,东营反超烟台!山东各地1-4月税收收入排行出炉

青岛下跌7.3%,东营反超烟台!山东各地1-4月税收收入排行出炉

水又木二
2024-06-15 17:43:14
足协酝酿超级罚单!3家俱乐部扣分或降级 会有泰山队吗?

足协酝酿超级罚单!3家俱乐部扣分或降级 会有泰山队吗?

球事百科吖
2024-06-15 18:10:08
将近40岁满脸褶,却尬演18岁少女,是谁给了她“强行装嫩”的勇气

将近40岁满脸褶,却尬演18岁少女,是谁给了她“强行装嫩”的勇气

娱乐圈十三太保
2024-05-28 13:56:53
沪深交易所发布重要调整!

沪深交易所发布重要调整!

新理财杂志
2024-06-15 11:20:08
杀人诛心!美法突然重磅宣布!

杀人诛心!美法突然重磅宣布!

大嘴说天下
2024-06-11 20:38:15
三个理由,证明A股超级大牛市即将展开!

三个理由,证明A股超级大牛市即将展开!

股海风云大作手
2024-06-15 19:31:40
贵州动态清零:悬崖呼救犹在耳边,万元低收人口已消失,逆袭标杆

贵州动态清零:悬崖呼救犹在耳边,万元低收人口已消失,逆袭标杆

大风文字
2024-06-15 09:56:17
广东一家三口全部染病,丈夫得知真相后,将妻子7刀捅死

广东一家三口全部染病,丈夫得知真相后,将妻子7刀捅死

纪实录
2024-06-09 18:39:35
周也凉凉!一部戏五替身,武替水替脚替背替马替,成下一个吴谨言

周也凉凉!一部戏五替身,武替水替脚替背替马替,成下一个吴谨言

八卦王者
2024-06-15 16:58:14
今日三场欧洲杯,真假意大利有看头

今日三场欧洲杯,真假意大利有看头

阿牛体育说
2024-06-16 00:21:25
2024-06-16 03:00:49
CSDN
CSDN
成就一亿技术人
24726文章数 241820关注度
往期回顾 全部

科技要闻

TikTok开始找退路了?

头条要闻

欧洲杯-亚马尔创纪录卡瓦哈尔首球 西班牙3-0克罗地亚

头条要闻

欧洲杯-亚马尔创纪录卡瓦哈尔首球 西班牙3-0克罗地亚

体育要闻

莱夫利,让困难为我让路

娱乐要闻

江宏杰秀儿女刺青,不怕刺激福原爱?

财经要闻

新情况!高层对人民币的态度180°转弯

汽车要闻

东风奕派eπ008售21.66万元 冰箱彩电都配齐

态度原创

健康
艺术
教育
数码
旅游

晚餐不吃or吃七分饱,哪种更减肥?

艺术要闻

穿越时空的艺术:《马可·波罗》AI沉浸影片探索人类文明

教育要闻

厉害!长沙15岁初三少年闯进2024年阿里巴巴全球数学竞赛决赛

数码要闻

低至 5747 元,爱普生 CH-TW6280T 真 4K 投影仪京东大促

旅游要闻

如何文艺消夏?乌镇10大活动开启古镇消夏节

无障碍浏览 进入关怀版