远控桌面服务器,Python 手把手实现远程控制桌面
作者 | 李秋鍵
責編 | 寇雪芹
頭圖 | 下載于視覺中國
本項目旨在讓大家理解遠控軟件的原理,通過遠控桌面可以實現遠程控制我們的電腦,更好更方便的管理電腦。文末將給出初始版的完整代碼,需要使用到的其他工具也會有所說明。最終實現的效果就是只要用戶點擊了客戶端的程序運行,我們就可以在服務端對其進行控制。效果如下:左邊是客服端程序運行了,然后我們就可以在左邊的另一臺電腦上打開服務端程序進行控制,可以看到左邊的屏幕圖像也已經顯示在了右邊的電腦上。完整代碼見文末!
遠控流程
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競賽獲獎等。
總結
以上是生活随笔為你收集整理的远控桌面服务器,Python 手把手实现远程控制桌面的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Handler的内功心法,值得拥有!
- 下一篇: python怎么创建桌面快捷_【原创py