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)点击“断开”可以断开当前连接。

posted on 2019-06-19 17:18  Hui会飞的鱼丶  阅读(3562)  评论(2编辑  收藏  举报