当前位置:   article > 正文

使用pyqt的QThread实现多线程的QTcpServer_pyqt qtcpserver

pyqt qtcpserver

本文章采用与《使用pyqt的QUdpSocket传文本信息、用QTcpServer传文件的样例》(该文章是从C++上的Qt收发文件的代码翻译过来的,个人认为过于复杂不易理解)不同的写法实现TCP收发文件,并增加多线程的功能。本文章的写法更接近于socketserver.ThreadingUDPServer、socketserver.ThreadingTCPServer的写法,可参考《使用socketserver的ThreadingUDPServer、ThreadingTCPServer实现收发消息和文件》
一共2个py文件:tcpClient.py、tcpServer.py

1.tcpClient.py只实现发送文件功能
2.tcpServer.py只实现接收文件功能,且有单线程和多线程两种方式
3.tcpClient.py+tcpServer.py(单线程)搭配使用,还提供了接收文件前的弹出窗口确认是否接收功能
4.tcpClient.py+tcpServer.py(多线程)搭配使用,无法实现接收文件前的弹出窗口确认是否接收功能,因为所有的QtWidgets部件,只能在QApplication主线程创建和使用,Qt不允许从子线程直接更新主线程里的QtWidgets部件。虽然可以自定义信号连接到自定义的槽函数调用QMessageBox.question(),但信号emit()后无法获取isReadyToRecvFile()返回值。
5.QThread简介: QThread类提供了一个与平台无关的管理线程的方法。
QThread的执行从run()函数的执行开始,run()函数退出,意味着线程的终止
run()函数通过调用exec()函数来启动事件循环机制,并且在线程内部处理Qt的事件。
QThread的用法:继承QThread类,重载Thread中的run()函数,调用start()函数来启动线程
6.还可以使用QThreadPool来管理QThread,本文不涉及,请自行研究。

客户端tcpClient.py代码:

# coding=utf-8
import os
import sys
import json
from PyQt6.QtCore import QFile
from PyQt6.QtWidgets import *
from PyQt6.QtNetwork import QHostAddress, QNetworkInterface, QAbstractSocket, QTcpSocket


class ClientWidget(QWidget):

    buffsize = 32 * 1024

    def __init__(self):
        super(ClientWidget, self).__init__()
        self.resize(500, 450)
        self.setWindowTitle('Client')
        self.progressbar = QProgressBar(self)
        self.browser = QTextBrowser(self)
        bt_sendFile = QPushButton('发送文件')
        bt_sendFile.clicked.connect(self.sendFile)
        layout = QVBoxLayout()
        layout.addWidget(self.progressbar)
        layout.addWidget(self.browser)
        layout.addWidget(bt_sendFile)
        self.setLayout(layout)

        self.localIP = self.getLocalIP()
        self.initTcpClient()

    def getLocalIP(self):
        '''获取本地主机IP'''
        for addr in QNetworkInterface.allAddresses():
            # 只要IPv4地址,过滤掉127.0.0.1
            if addr.protocol() == QAbstractSocket.NetworkLayerProtocol.IPv4Protocol and addr != QHostAddress.SpecialAddress.LocalHost:
                address = addr.toString()
                # 169开头的IP地址表示本地主机未从DHCP分配到有效IP,过滤网关地址x.x.x.1
                if address[:3] != '169' and address.split('.')[-1] != '1':
                    return address
        return '0.0.0.0'

    def initTcpClient(self):
        self.tcpSocket = QTcpSocket()
        self.tcpSocket.connected.connect(self.onTcpClientConnected)
        self.tcpSocket.disconnected.connect(self.onDisconnected)

    def onTcpClientConnected(self):
        peer_address = self.tcpSocket.peerAddress().toString()
        peer_port = self.tcpSocket.peerPort()
        news = 'Connected with address {}, port {}'.format(peer_address, str(peer_port))
        self.browser.append(news)

        filePath = self.tcpSocket.dt['msg']
        self.tcpSocket.dt['msg'] = os.path.basename(filePath)  # 只传文件名
        self.tcpSocket.dt['size'] = os.stat(filePath)[6]  # 文件大小(字节)
        dt_encode = json.dumps(self.tcpSocket.dt).encode('utf-8')
        self.tcpSocket.write(dt_encode)
        if self.tcpSocket.waitForReadyRead():  # 等待对方回复是否同意接收文件
            data = self.tcpSocket.readAll()
            if data == b'ready':
                fromFile = QFile(filePath)
                if not fromFile.open(QFile.OpenModeFlag.ReadOnly):
                    self.browser.append('无法打开要发送的文件:%s' % filePath)
                    self.tcpSocket.close()
                    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/187357
推荐阅读
相关标签
  

闽ICP备14008679号