当前位置: 首页 > news >正文

Qt/C++ 实现文件双向传输:从客户端到服务端,再从服务端到客户端

Qt/cpp实现的客户端往服务端传输文件、服务端往客户端传输文件,可监测传输状态,可控制传输。 源码: 使用Qt5.6.1_MinGW编译通过。 c.37

在很多网络应用场景中,文件的双向传输,也就是客户端往服务端传输文件以及服务端往客户端传输文件,并且能够监测传输状态和对传输进行控制,是非常常见的需求。今天就来聊聊如何使用 Qt/C++ 来实现这一功能。

一、环境说明

本文的代码使用 Qt5.6.1_MinGW 编译通过,确保你也配置好了相应的开发环境,以便顺利运行和理解代码。

二、客户端往服务端传输文件

1. 建立连接

首先,我们需要在客户端和服务端之间建立一个 TCP 连接。在 Qt 中,可以使用 QTcpSocket 来实现。

QTcpSocket *socket = new QTcpSocket(this); socket->connectToHost(QHostAddress::LocalHost, 1234); if(socket->waitForConnected(5000)) { qDebug() << "Connected to server!"; } else { qDebug() << "Could not connect: " << socket->errorString(); }

这里我们创建了一个 QTcpSocket 对象,并尝试连接到本地主机的 1234 端口。waitForConnected函数会阻塞等待,直到连接建立或者超时,这里设置的超时时间是 5 秒。如果连接成功,会输出连接成功的信息,否则输出错误信息。

2. 文件传输

接下来进行文件传输。假设我们要传输的文件是test.txt

QFile file("test.txt"); if(!file.open(QIODevice::ReadOnly)) { qDebug() << "Could not open file"; return; } qint64 totalBytes = file.size(); qint64 bytesWritten = 0; qint64 bytesToWrite = totalBytes; while(bytesToWrite > 0) { QByteArray buffer = file.read(qMin(bytesToWrite, (qint64)1024)); qint64 written = socket->write(buffer); if(written == -1) { qDebug() << "Write error: " << socket->errorString(); break; } bytesWritten += written; bytesToWrite -= written; qDebug() << "Transferred " << bytesWritten << " of " << totalBytes << " bytes"; } file.close(); socket->close();

首先打开要传输的文件,如果打开失败则输出错误信息并返回。获取文件的总大小totalBytes,然后循环读取文件内容并写入到 socket 中。每次读取最多 1024 字节的数据,写入成功后更新已传输字节数bytesWritten和剩余要传输字节数bytesToWrite,并输出当前传输进度。传输完成后关闭文件和 socket。

3. 监测传输状态

为了监测传输状态,我们可以在传输过程中实时输出已传输字节数和总字节数,就像上面代码中那样。也可以使用信号槽机制,比如QTcpSocketbytesWritten信号。

connect(socket, SIGNAL(bytesWritten(qint64)), this, SLOT(updateTransferProgress(qint64))); void MyClass::updateTransferProgress(qint64 bytes) { static qint64 totalBytes = 0; totalBytes += bytes; qDebug() << "Transferred " << totalBytes << " bytes so far"; }

这里将bytesWritten信号连接到自定义的槽函数updateTransferProgress,在槽函数中累加已传输字节数并输出。

4. 控制传输

可以通过一些逻辑来控制传输,比如暂停和继续。我们可以在连接成功后设置一个标志位来表示传输状态。

bool isPaused = false; // 假设这里有一个暂停按钮的点击事件槽函数 void MyClass::onPauseButtonClicked() { isPaused = true; socket->pause(); } // 继续按钮的点击事件槽函数 void MyClass::onResumeButtonClicked() { isPaused = false; socket->resume(); }

当点击暂停按钮时,设置isPaused为 true 并调用socket->pause()暂停传输;点击继续按钮时,设置isPaused为 false 并调用socket->resume()继续传输。

三、服务端往客户端传输文件

1. 监听连接

服务端需要监听客户端的连接请求,使用 QTcpServer 来实现。

QTcpServer *server = new QTcpServer(this); if(!server->listen(QHostAddress::LocalHost, 1234)) { qDebug() << "Could not start server: " << server->errorString(); return; } connect(server, SIGNAL(newConnection()), this, SLOT(handleNewConnection()));

创建一个 QTcpServer 对象并尝试监听本地主机的 1234 端口。如果监听失败,输出错误信息并返回。将newConnection信号连接到自定义的槽函数handleNewConnection,当有新的客户端连接时会调用这个槽函数。

2. 文件传输

handleNewConnection槽函数中进行文件传输。假设要传输的文件也是test.txt

void MyClass::handleNewConnection() { QTcpSocket *socket = server->nextPendingConnection(); QFile file("test.txt"); if(!file.open(QIODevice::ReadOnly)) { qDebug() << "Could not open file"; socket->close(); return; } qint64 totalBytes = file.size(); qint64 bytesWritten = 0; qint64 bytesToWrite = totalBytes; while(bytesToWrite > 0) { QByteArray buffer = file.read(qMin(bytesToWrite, (qint64)1024)); qint64 written = socket->write(buffer); if(written == -1) { qDebug() << "Write error: " << socket->errorString(); break; } bytesWritten += written; bytesToWrite -= written; qDebug() << "Transferred " << bytesWritten << " of " << totalBytes << " bytes"; } file.close(); socket->close(); }

这里获取新连接的 socket,打开要传输的文件,然后和客户端往服务端传输文件类似,循环读取文件内容并写入到 socket 中,实时输出传输进度。传输完成后关闭文件和 socket。

3. 监测传输状态与控制传输

和客户端类似,服务端也可以通过信号槽机制监测传输状态,比如使用bytesWritten信号。控制传输的逻辑也可以类似实现,设置标志位并通过相应的函数来暂停和继续传输。

通过以上步骤,我们就实现了 Qt/C++ 客户端往服务端传输文件、服务端往客户端传输文件,并且能够监测传输状态和控制传输的功能。希望这篇文章对你在网络文件传输相关的开发中有帮助。

http://www.jsqmd.com/news/89408/

相关文章:

  • c#教程实战应用案例分享
  • 第二章——数据分析场景之Python数据可视化:用Matplotlib与Seaborn绘制洞察之图
  • TTS 之 PYTHON库 pyttsx3
  • 【开题答辩全过程】以 基于Spring Boot的香飘万里外卖平台为例,包含答辩的问题和答案
  • 从零解决pyproject.toml构建失败的实战指南
  • Linux系统中的socket激活:先创建监听端口,后启动程序
  • 实战LLaMA2-7B指令微调
  • 优化Sigmoid函数计算:提升AI模型训练速度
  • 华强北看了都慌!酷铂达平替千元耳机,降噪+环绕声双buff拉满
  • 亚马逊基本功:低成本测品攻略
  • Java 八大排序算法详解(从入门到面试)
  • 【和春笋一起学C++】(五十一)复制构造函数
  • AI如何革新漏洞扫描工具的开发流程
  • 题解:AT_abc436_f
  • 计算机毕业设计springboot餐厅预定系统 基于SpringBoot的智慧餐饮订座平台 SpringBoot驱动的线上餐厅席位预约管理系统
  • 小白程序员的进阶之路:Java大厂求职面试实录
  • mac 安装brew实战应用案例分享
  • 深入解析 DNS:互联网的隐形神经系统
  • 服务器文件管理太麻烦?宝塔 FTP+cpolar 让远程操作像本地一样简单
  • 破壁异构计算 - Ascend C在CANN全栈中的战略支点角色
  • 数字色彩的骨架:计算机如何理解颜色
  • vue基于springboot众筹平台的设计与实现_o6xzhq2s_
  • MATLAB 环境下信号的同步压缩广义 Stockwell 变换探索
  • UE5 材质-35-节点:CustomRotator 自定义旋转 节点。线性渐变节点,材质函数 LinearGradient。
  • AI大模型赋能消费升级:新机遇与新路径
  • vue基于springboot的社区健身服务_yob3w0op_
  • Web3.js钱包与账户管理
  • 【开题答辩全过程】以 基于微信小程序的失物认领系统为例,包含答辩的问题和答案
  • Ascend C算子精度调试全攻略 - 从Print函数到结构化数据比对
  • 安全体验馆好用供应商