PyQt5綜合實踐—TCP服務器


目的:實現一個可以用於接收和發送文本的TCP服務器。

思路 :

1. 兩個QLineEdit用於服務器ip和port的輸入,同時會限制ip和port的輸入。

2. 一個QPushButton,點擊后開始“監聽”,並把連接的過程放到一個線程thread中,這樣不會在等待連接的過程中造成程序阻塞。

3. 一個QlineEdit用於顯示連接后的客戶端地址和端口信息。

4. 再來一個QPushButton,關閉當前連接,如果當前連接不存在,則提示“沒有連接”。

5. 增加兩個QLineEdit用於輸入發送數據,和顯示接收數據。

 

1. 這里直接使用QtDesginer布局,配合GroupBox控件擺了5個QLineEdit和3個QPushButton ,保存為testGUI.ui 。

 

2. 用PyUIC轉化為python代碼,生成文件testGUI.py:

  1 # -*- coding: utf-8 -*-
  2 
  3 # Form implementation generated from reading ui file 'testGUi.ui'
  4 #
  5 # Created by: PyQt5 UI code generator 5.11.3
  6 #
  7 # WARNING! All changes made in this file will be lost!
  8 
  9 from PyQt5 import QtCore, QtGui, QtWidgets
 10 
 11 class Ui_MainWindow(object):
 12     def setupUi(self, MainWindow):
 13         MainWindow.setObjectName("MainWindow")
 14         MainWindow.resize(547, 214)
 15         sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
 16         sizePolicy.setHorizontalStretch(0)
 17         sizePolicy.setVerticalStretch(0)
 18         sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
 19         MainWindow.setSizePolicy(sizePolicy)
 20         self.centralwidget = QtWidgets.QWidget(MainWindow)
 21         self.centralwidget.setObjectName("centralwidget")
 22         self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
 23         self.groupBox.setGeometry(QtCore.QRect(10, 10, 331, 41))
 24         self.groupBox.setObjectName("groupBox")
 25         self.listenButton = QtWidgets.QPushButton(self.groupBox)
 26         self.listenButton.setGeometry(QtCore.QRect(260, 14, 61, 21))
 27         sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
 28         sizePolicy.setHorizontalStretch(1)
 29         sizePolicy.setVerticalStretch(0)
 30         sizePolicy.setHeightForWidth(self.listenButton.sizePolicy().hasHeightForWidth())
 31         self.listenButton.setSizePolicy(sizePolicy)
 32         self.listenButton.setObjectName("listenButton")
 33         self.layoutWidget = QtWidgets.QWidget(self.groupBox)
 34         self.layoutWidget.setGeometry(QtCore.QRect(10, 13, 241, 22))
 35         self.layoutWidget.setObjectName("layoutWidget")
 36         self.horizontalLayout = QtWidgets.QHBoxLayout(self.layoutWidget)
 37         self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
 38         self.horizontalLayout.setObjectName("horizontalLayout")
 39         self.ipLabel = QtWidgets.QLabel(self.layoutWidget)
 40         self.ipLabel.setObjectName("ipLabel")
 41         self.horizontalLayout.addWidget(self.ipLabel)
 42         self.ipLineEdit = QtWidgets.QLineEdit(self.layoutWidget)
 43         self.ipLineEdit.setObjectName("ipLineEdit")
 44         self.horizontalLayout.addWidget(self.ipLineEdit)
 45         self.portLabel = QtWidgets.QLabel(self.layoutWidget)
 46         self.portLabel.setObjectName("portLabel")
 47         self.horizontalLayout.addWidget(self.portLabel)
 48         self.portLineEdit = QtWidgets.QLineEdit(self.layoutWidget)
 49         self.portLineEdit.setObjectName("portLineEdit")
 50         self.horizontalLayout.addWidget(self.portLineEdit)
 51         self.horizontalLayout.setStretch(0, 1)
 52         self.horizontalLayout.setStretch(1, 4)
 53         self.horizontalLayout.setStretch(2, 1)
 54         self.horizontalLayout.setStretch(3, 2)
 55         self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget)
 56         self.groupBox_2.setGeometry(QtCore.QRect(350, 10, 181, 41))
 57         self.groupBox_2.setObjectName("groupBox_2")
 58         self.connectLineEdit = QtWidgets.QLineEdit(self.groupBox_2)
 59         self.connectLineEdit.setGeometry(QtCore.QRect(10, 13, 111, 19))
 60         self.connectLineEdit.setReadOnly(True)
 61         self.connectLineEdit.setObjectName("connectLineEdit")
 62         self.disconnectButton = QtWidgets.QPushButton(self.groupBox_2)
 63         self.disconnectButton.setGeometry(QtCore.QRect(130, 12, 41, 21))
 64         sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
 65         sizePolicy.setHorizontalStretch(1)
 66         sizePolicy.setVerticalStretch(0)
 67         sizePolicy.setHeightForWidth(self.disconnectButton.sizePolicy().hasHeightForWidth())
 68         self.disconnectButton.setSizePolicy(sizePolicy)
 69         self.disconnectButton.setObjectName("disconnectButton")
 70         self.sendLineEdit = QtWidgets.QLineEdit(self.centralwidget)
 71         self.sendLineEdit.setGeometry(QtCore.QRect(60, 70, 281, 31))
 72         self.sendLineEdit.setObjectName("sendLineEdit")
 73         self.sendButton = QtWidgets.QPushButton(self.centralwidget)
 74         self.sendButton.setGeometry(QtCore.QRect(360, 70, 75, 31))
 75         self.sendButton.setObjectName("sendButton")
 76         self.recvLineEdit = QtWidgets.QLineEdit(self.centralwidget)
 77         self.recvLineEdit.setGeometry(QtCore.QRect(60, 120, 281, 31))
 78         self.recvLineEdit.setObjectName("recvLineEdit")
 79         self.label = QtWidgets.QLabel(self.centralwidget)
 80         self.label.setGeometry(QtCore.QRect(20, 80, 31, 16))
 81         self.label.setObjectName("label")
 82         self.label_2 = QtWidgets.QLabel(self.centralwidget)
 83         self.label_2.setGeometry(QtCore.QRect(20, 130, 31, 16))
 84         self.label_2.setObjectName("label_2")
 85         self.groupBox_2.raise_()
 86         self.groupBox.raise_()
 87         self.sendLineEdit.raise_()
 88         self.sendButton.raise_()
 89         self.recvLineEdit.raise_()
 90         self.label.raise_()
 91         self.label_2.raise_()
 92         MainWindow.setCentralWidget(self.centralwidget)
 93         self.menubar = QtWidgets.QMenuBar(MainWindow)
 94         self.menubar.setGeometry(QtCore.QRect(0, 0, 547, 23))
 95         self.menubar.setObjectName("menubar")
 96         MainWindow.setMenuBar(self.menubar)
 97         self.statusbar = QtWidgets.QStatusBar(MainWindow)
 98         self.statusbar.setObjectName("statusbar")
 99         MainWindow.setStatusBar(self.statusbar)
100 
101         self.retranslateUi(MainWindow)
102         QtCore.QMetaObject.connectSlotsByName(MainWindow)
103 
104     def retranslateUi(self, MainWindow):
105         _translate = QtCore.QCoreApplication.translate
106         MainWindow.setWindowTitle(_translate("MainWindow", "Test Tool"))
107         self.groupBox.setTitle(_translate("MainWindow", "網絡配置"))
108         self.listenButton.setText(_translate("MainWindow", "開始監聽"))
109         self.ipLabel.setText(_translate("MainWindow", "IP地址:"))
110         self.portLabel.setText(_translate("MainWindow", "端口:"))
111         self.groupBox_2.setTitle(_translate("MainWindow", "當前連接"))
112         self.disconnectButton.setText(_translate("MainWindow", "斷開"))
113         self.sendButton.setText(_translate("MainWindow", "發送"))
114         self.label.setText(_translate("MainWindow", "發送:"))
115         self.label_2.setText(_translate("MainWindow", "接收:"))
View Code

3. 繼承testGUI,實現主要功能:

 1 import sys
 2 import socket
 3 import threading
 4 from PyQt5.QtCore import QRegExp
 5 from PyQt5.QtGui import QIntValidator,QRegExpValidator
 6 from PyQt5.QtWidgets import QApplication,QMainWindow
 7 from test.testGUi import Ui_MainWindow
 8 
 9 class TestGUI(Ui_MainWindow):
10 
11     def __init__(self, MainWindow):
12         """
13         初始化界面 ,連接槽函數,以及設置校驗器
14         """
15         self.setupUi(MainWindow)
16         self.connect_slot()
17         self.server_validator()
18 
19     def start_tcp_server(self):
20         # 設置 “開始監聽” 按鈕不可用
21         self.listenButton.setDisabled(True)
22         # 實例化一個socket
23         self.sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
24         try:
25             ipText = self.ipLineEdit.text()
26             portValue = int(self.portLineEdit.text())
27             self.sock.bind((ipText,portValue))
28         except Exception as e:
29             print("請檢查ip和端口號")
30             print(e)
31         else:
32             self.sock.listen(1)
33             # 創建一個進程,用於處理socket連接和接收數據
34             server_th = threading.Thread(target=self.tcp_connect_concurrency)
35             server_th.start()
36             print("正在監聽")
37 
38     # 進程函數
39     def tcp_connect_concurrency(self):
40         try:
41             connect ,address = self.sock.accept()
42         except Exception as e:
43             print(e)
44         self.base_connect = connect
45         connect_address = address[0] + ":" + str(address[1])
46         self.connectLineEdit.setText(connect_address)
47         while True:
48             recv_msg = self.base_connect.recv(1024)
49             self.recvLineEdit.setText(recv_msg.decode('utf-8'))
50 
51     def tcp_close(self):
52         """
53         點擊'disconnect'按鈕,斷開當前連接
54         """
55         if self.listenButton.isEnabled()==False:
56             self.listenButton.setDisabled(False)
57         try:
58             self.base_connect.close()
59             self.connectLineEdit.setText("")
60         except AttributeError as e:
61             pass
62         except Exception as e:
63             print(e)
64 
65     def send_text(self):
66         """
67         點擊“發送”發送數據/文本
68         """
69         send_msg = self.sendLineEdit.text()
70         self.base_connect.send(send_msg.encode('utf-8'))
71 
72     def server_validator(self):
73         """
74         設置 ip 和 port 文本輸入框的限制
75         """
76         ipValidator = QRegExpValidator(QRegExp('^((2[0-4]\d|25[0-5]|\d?\d|1\d{2})\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$'))
77         portValidator = QIntValidator(0,65535)
78         self.ipLineEdit.setValidator(ipValidator)
79         self.portLineEdit.setValidator(portValidator)
80         self.ipLineEdit.setPlaceholderText("請輸入ip地址")
81         self.portLineEdit.setPlaceholderText("端口")
82 
83     def connect_slot(self):
84         """連接各控件的槽函數"""
85         self.listenButton.clicked.connect(self.start_tcp_server)
86         self.disconnectButton.clicked.connect(self.tcp_close)
87         self.sendButton.clicked.connect(self.send_text)
88 
89 if __name__ == '__main__':
90     app = QApplication(sys.argv)
91     mainWindow = QMainWindow()
92     ui = TestGUI(mainWindow)
93     mainWindow.show()
94     sys.exit(app.exec_())
View Code

4. 運行后的結果:

  1)先運行mainGUI.py ,輸入如下IP地址和端口號,點擊“開始監聽”,然后運行server.py,就能獲取到連接了。

        

  2)發送文本框輸入"你好",點擊“發送” ,client收到發送的內容,並發送文本"Hi"

        

   3)點擊“斷開”可以斷開當前連接。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM