在这个周末刚刚写进去的python桌面利用--网络聊天室,次要通过pyqt5作为桌面利用框架,socket作为网络编程的框架,从而实现包含客户端和服务端的网络聊天室的GUI利用,心愿能够一起学习、一起提高!

利用包含服务端server_ui.py、客户端client_ui.py两个python模块实现,并且在pyqt5的应用过程中都应用QThread多线程利用以及根本的UI页面布局。开始之前通过一个动态图来察看一下socket服务端、socket客户端通信的实现成果。

【浏览全文】

  1. socket_ui.py 服务端

1-1. 依赖援用

在socket服务端的实现过程中,除了pyqt5相干的UI界面的援用外,还包含time、threading、sys、socket等辅助模块来一起实现socket服务端的桌面应用程序。

from PyQt5.QtWidgets import *from PyQt5.QtCore import *from PyQt5.QtGui import *import sysfrom QCandyUi import CandyWindow# 导入 socket 通信模块import socket# 导入工夫治理模块import time# 导入多线程模块import threading

1-2. 实现过程

在服务端的业务实现下面,咱们仍然是依照之前的GUI实现形式,采纳主线程用来实现页面布局,子线程QThread来实现业务逻辑的形式来进行实现的,socket的服务端通信业务都是在子线程ServerThread中编写的。上面是socket服务端桌面利用实现的全副代码块,copy到本人的ide中即可间接启动应用。

class ServerUI(QWidget):    def __init__(self):        super(ServerUI, self).__init__()        self.init_ui()    def init_ui(self):        self.setWindowTitle('socket 服务端  公众号:[Python 集中营]')        self.setWindowIcon(QIcon('hi.ico'))        self.setFixedSize(500, 300)        hbox = QHBoxLayout()        hbox_v1 = QVBoxLayout()        self.brower = QTextBrowser()        self.brower.setFont(QFont('宋体', 8))        self.brower.setReadOnly(True)        self.brower.setPlaceholderText('音讯展现区域...')        self.brower.ensureCursorVisible()        hbox_v1.addWidget(self.brower)        hbox_v2 = QVBoxLayout()        hbox_v2_f1 = QFormLayout()        self.ip_label = QLabel()        self.ip_label.setText('ip地址 ')        self.ip_txt = QLineEdit()        self.ip_txt.setPlaceholderText('0.0.0.0')        self.port_label = QLabel()        self.port_label.setText('端口 ')        self.port_txt = QLineEdit()        self.port_txt.setPlaceholderText('4444')        self.lis_num_label = QLabel()        self.lis_num_label.setText('最大监听个数 ')        self.lis_num_txt = QLineEdit()        self.lis_num_txt.setPlaceholderText('10')        self.close_cli_label = QLabel()        self.close_cli_label.setText('客户端敞开指令 ')        self.close_cli_txt = QLineEdit()        self.close_cli_txt.setPlaceholderText('exit,客户端发送相应指令则敞开')        hbox_v2_f1.addRow(self.ip_label, self.ip_txt)        hbox_v2_f1.addRow(self.port_label, self.port_txt)        hbox_v2_f1.addRow(self.lis_num_label, self.lis_num_txt)        hbox_v2_f1.addRow(self.close_cli_label, self.close_cli_txt)        self.start_btn = QPushButton()        self.start_btn.setText('开启服务端')        self.start_btn.clicked.connect(self.start_btn_clk)        hbox_v2.addLayout(hbox_v2_f1)        hbox_v2.addWidget(self.start_btn)        hbox.addLayout(hbox_v1)        hbox.addLayout(hbox_v2)        self.thread_ = ServerThread(self)        self.thread_.message.connect(self.show_message)        self.setLayout(hbox)    def show_message(self, text):        '''        槽函数:向文本浏览器中写入内容        :param text:        :return:        '''        cursor = self.brower.textCursor()        cursor.movePosition(QTextCursor.End)        self.brower.append(text)        self.brower.setTextCursor(cursor)        self.brower.ensureCursorVisible()    def start_btn_clk(self):        self.thread_.start()        self.start_btn.setEnabled(False)class ServerThread(QThread):    message = pyqtSignal(str)    def __init__(self, parent=None):        super(ServerThread, self).__init__(parent)        self.parent = parent        self.working = True    def __del__(self):        self.working = False        self.wait()    def run(self):        self.message.emit('筹备启动socket服务端...')        # 创立服务端 socket        socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        # 绑定服务地址、端口        address = (self.parent.ip_txt.text().strip(), int(self.parent.port_txt.text().strip()))        socket_server.bind(address)        # 设置监听最大期待数        socket_server.listen(int(self.parent.lis_num_txt.text().strip()))        self.message.emit("服务曾经启动,正在期待客户端连贯...")        while True:            # 设置睡眠工夫            time.sleep(0.1)            # 容许客户端连贯            client, info = socket_server.accept()            self.client, self.info = client, info            # 启用新线程调用音讯解决            thread = threading.Thread(target=self.catch_message)            # 设置为守护线程            thread.setDaemon(True)            # 开启线程执行            thread.start()    def catch_message(self):        self.client.send("欢送来到网络聊天室".encode('utf-8'))        self.message.emit("客户端信息:" + str(self.info))        close_cli = self.parent.close_cli_txt.text().strip()        while True:            try:                #  接管客户端音讯、接管最大长度为 1024,并进行 utf-8 解码                message = self.client.recv(1024).decode('utf-8')                # 校验是否敞开客户端                if not message and close_cli == message:                    self.client.close()                    self.message.emit("以后客户端已敞开!")                    break                self.message.emit("接管到音讯:" + message)                # 将音讯进行 utf-8 编码后发给客户端                rcv = "服务端胜利接管音讯:" + message                self.client.send(rcv.encode('utf-8'))            except Exception as e:                self.client.send("服务端解决音讯异样!".encode('utf-8'))                breakif __name__ == '__main__':    app = QApplication(sys.argv)    w = CandyWindow.createWindow(ServerUI(), theme='blueGreen', title='socket 服务端  公众号:[Python 集中营]',                                 ico_path='hi.ico')    w.show()    sys.exit(app.exec_())

1-3. 实现成果

  1. client_ui.py 客户端

2-1. 依赖援用

在socket客户端的实现过程中,除了pyqt5相干的UI界面的援用外,还包含sys、socket等辅助模块来一起实现socket服务端的桌面应用程序,相比服务端来说,客户端并没有应用多线程threading模块。

from PyQt5.QtWidgets import *from PyQt5.QtCore import *from PyQt5.QtGui import *import sysfrom QCandyUi import CandyWindow# 导入socket 通信模块import socket

2-2. 实现过程

客户端的实现过程和服务端server_ui.py实现是根本类似的,同样也应用到了pyqt5的QThread的子线程利用,惟一不同的是socket客户端通信形式跟服务端不大雷同,同样将上面的代码块copy到本人的ide中间接应用即可。

class ClientUI(QWidget):    def __init__(self):        super(ClientUI, self).__init__()        self.init_ui()    def init_ui(self):        self.setWindowTitle('socket 客户端  公众号:[Python 集中营]')        self.setWindowIcon(QIcon('hi.ico'))        self.setFixedSize(500, 300)        hbox = QHBoxLayout()        hbox_v1 = QVBoxLayout()        self.brower = QTextBrowser()        self.brower.setFont(QFont('宋体', 8))        self.brower.setReadOnly(True)        self.brower.setPlaceholderText('音讯展现区域...')        self.brower.ensureCursorVisible()        hbox_v1.addWidget(self.brower)        hbox_v2 = QVBoxLayout()        hbox_v2_g1 = QGridLayout()        self.ip_label = QLabel()        self.ip_label.setText('ip地址 ')        self.ip_txt = QLineEdit()        self.ip_txt.setPlaceholderText('0.0.0.0')        self.port_label = QLabel()        self.port_label.setText('端口 ')        self.port_txt = QLineEdit()        self.port_txt.setPlaceholderText('4444')        self.message = QTextEdit()        self.message.setPlaceholderText('发送音讯内容...')        hbox_v2_g1.addWidget(self.ip_label, 0, 0, 1, 1)        hbox_v2_g1.addWidget(self.ip_txt, 0, 1, 1, 1)        hbox_v2_g1.addWidget(self.port_label, 1, 0, 1, 1)        hbox_v2_g1.addWidget(self.port_txt, 1, 1, 1, 1)        hbox_v2_g1.addWidget(self.message, 2, 0, 1, 2)        self.start_btn = QPushButton()        self.start_btn.setText('发送音讯')        self.start_btn.clicked.connect(self.start_btn_clk)        hbox_v2.addLayout(hbox_v2_g1)        hbox_v2.addWidget(self.start_btn)        hbox.addLayout(hbox_v1)        hbox.addLayout(hbox_v2)        self.thread_ = ClientThread(self)        self.thread_.message.connect(self.show_message)        self.setLayout(hbox)    def show_message(self, text):        '''        槽函数:向文本浏览器中写入内容        :param text:        :return:        '''        cursor = self.brower.textCursor()        cursor.movePosition(QTextCursor.End)        self.brower.append(text)        self.brower.setTextCursor(cursor)        self.brower.ensureCursorVisible()    def start_btn_clk(self):        self.thread_.start()class ClientThread(QThread):    message = pyqtSignal(str)    def __init__(self, parent=None):        super(ClientThread, self).__init__(parent)        self.parent = parent        self.working = True        self.is_connect = False    def __del__(self):        self.working = False        self.wait()    def run(self):        try:            if self.is_connect is False:                self.connect_serv()            # 将控制台输出音讯进行 utf-8 编码后发送            self.socket_client.send(self.parent.message.toPlainText().strip().encode('utf-8'))            self.message.emit(self.socket_client.recv(1024).decode('utf-8'))        except Exception as e:            self.message.emit("发送音讯异样:" + str(e))    def connect_serv(self):        try:            self.message.emit("正在创立客户端socket...")            # 创立客户端 socket            self.socket_client = socket.socket()            # 连贯服务端            address = (self.parent.ip_txt.text().strip(), int(self.parent.port_txt.text().strip()))            self.socket_client.connect(address)            self.message.emit("服务端连贯胜利...")            # 接管服务端音讯并进行 utf-8 解码            self.message.emit(self.socket_client.recv(1024).decode())            self.is_connect = True        except:            self.is_connect = Falseif __name__ == '__main__':    app = QApplication(sys.argv)    w = CandyWindow.createWindow(ClientUI(), theme='blueGreen', title='socket 客户端  公众号:[Python 集中营]',                                 ico_path='hi.ico')    w.show()    sys.exit(app.exec_())

2-3. 实现成果

【往期精彩】

零配置python日志,装置即用!

英语没学好到底能不能做coder,别再纠结了先学起来...

数据荡涤工具flashtext,效率间接晋升了几十倍数!

一个help函数解决了python的所有文档信息查看...

python 自定义异样/raise关键字抛出异样