赞
踩
本文章采用与《使用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()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。