qt 使用线程池传输文件的时候,接受端在接收了一点点数据后就在执行readAll()时未响应了,调试的时候提示段错误。放在主线程接收的时候是可以正常接收的。
6条回答 默认 最新
关注
引自免费微信小程序:皆我百晓生
根据您提供的信息,问题可能出现在多线程环境中对QTcpSocket的使用不当。在并发环境中,多个线程同时访问同一个QTcpSocket实例可能会导致竞态条件和数据同步问题。为了解决这个问题,您可以尝试将QTcpSocket对象封装在一个单独的类中,确保对它的所有操作都在一个线程内完成。此外,您还可以考虑使用信号槽机制处理网络事件,这样可以简化线程间的通信。
首先,我们将创建一个新的类
TcpConnectionHandler
,它负责管理QTcpSocket的生命周期和读写操作。这个类将在一个单独的工作线程中运行。class TcpConnectionHandler : public QObject { Q_OBJECT public: explicit TcpConnectionHandler(QObject *parent = nullptr); ~TcpConnectionHandler(); void startHandling(qintptr socketDescriptor); signals: void fileReceived(const QString &filePath); void connectionClosed(); private slots: void onReadyRead(); void onConnected(); void onError(QAbstractSocket::SocketError error); void onDisconnected(); private: QTcpSocket *m_socket; QDataStream m_stream; };
接下来实现
TcpConnectionHandler
的成员函数:#include <QObject> #include <QTcpSocket> #include <QDataStream> #include <QFile> TcpConnectionHandler::TcpConnectionHandler(QObject *parent) : QObject(parent), m_socket(new QTcpSocket(this)), m_stream(m_socket) { connect(m_socket, &QTcpSocket::readyRead, this, &TcpConnectionHandler::onReadyRead); connect(m_socket, &QTcpSocket::connected, this, &TcpConnectionHandler::onConnected); connect(m_socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QTcpSocket::error), this, &TcpConnectionHandler::onError); connect(m_socket, &QTcpSocket::disconnected, this, &TcpConnectionHandler::onDisconnected); } TcpConnectionHandler::~TcpConnectionHandler() { if (m_socket->state() != QTcpSocket::UnconnectedState) { m_socket->close(); } delete m_socket; } void TcpConnectionHandler::startHandling(qintptr socketDescriptor) { m_socket->setSocketDescriptor(socketDescriptor); m_socket->waitForConnected(-1); } void TcpConnectionHandler::onReadyRead() { quint64 filenameSize; QString fileInfo; quint64 fileSize; // 解析文件信息 m_stream >> filenameSize >> fileInfo >> fileSize; received_file_size = fileSize; // 创建文件 fileName = file_storage_address + fileInfo.mid(16); QFile file(fileName); if (!file.open(QIODevice::ReadWrite)) { emit connectionClosed(); return; } while (file.isOpen()) { QByteArray data = m_socket->readAll(); if (data.isEmpty()) { break; } file.write(data); received_file_size -= data.size(); } if (fileSize == received_file_size) { file.close(); emit fileReceived(fileName); } else { emit connectionClosed(); } } void TcpConnectionHandler::onConnected() { qDebug() << "连接成功"; } void TcpConnectionHandler::onError(QAbstractSocket::SocketError error) { qDebug() << "发生错误:" << error; emit connectionClosed(); } void TcpConnectionHandler::onDisconnected() { qDebug() << "连接断开"; emit connectionClosed(); }
现在,在
Receive
类中,我们不需要再使用线程池,而是创建一个TcpConnectionHandler
实例并传递给工作线程:void Receive::run() { QEventLoop loop; TcpConnectionHandler handler(this); if (ip_address == "") { handler.startHandling(handle); // 服务器接收 } else { QTcpSocket *socket = new QTcpSocket(this); socket->connectToHost(ip_address, 1880); // 客户端接受 if (!socket->waitForConnected(-1)) { delete socket; return; } handler.m_socket->setSocketDescriptor(socket->socketDescriptor()); } connect(&handler, &TcpConnectionHandler::fileReceived, this, &Receive::fileReceived); connect(&handler, &TcpConnectionHandler::connectionClosed, &loop, &QEventLoop::quit); loop.exec(); }
在这个修改后的版本中,
Receive
类不再直接操作QTcpSocket,而是通过TcpConnectionHandler
来处理网络事件。这应该能解决你在多线程环境中遇到的问题。记得替换掉旧的代码,并重新编译和测试您的应用。如果还有其他问题,请随时告诉我。解决 无用评论 打赏 举报 编辑记录
悬赏问题
- ¥20 大数据采集用Python爬取猫眼电影数据
- ¥15 用freertos后NVIC里系统时钟部分报错
- ¥15 后缀表达式的计算算法问题
- ¥15 安装mid360驱动后,执行rviz_MID360.launch rviz不显示
- ¥15 关于#人工智能#的问题:(2)设计一个GUI,允许语音和文本实现谣言的检测
- ¥50 请教 麒麟系统挂载怎么安装
- ¥15 如何在ns3中实现路径的自由切换
- ¥20 SpringBoot+Vue3
- ¥15 IT从业者的调查问卷
- ¥65 LineageOs-21.0系统编译问题