QT:tftp client 和 Server

1.TFTP简介

TFTP(Trivial File Transfer Protocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。端口号为69。

FTP是一个传输文件的简单协议,它基于UDP协议而实现,但是我们也不能确定有些TFTP协议是基于其它传输协议完成的。此协议设计的时候是进行小文件传输的。因此它不具备通常的FTP的许多功能,它只能从文件服务器上获得或写入文件,不能列出目录,不进行认证,它传输8位数据。传输中有三种模式:netascii,这是8位的ASCII码形式,另一种是octet,这是8位源数据类型;最后一种mail已经不再支持,它将返回的数据直接返回给用户而不是保存为文件。

参考链接:https://blog.csdn.net/weixin_43996145/article/details/134265843?spm=1001.2014.3001.5501

2.TFTP Client

2.1 界面

在这里插入图片描述

2.2 源码

uint32_t ClientSocket::write(const char* data, size_t size)
{return socket_->write(data, size);
}TFtpClient::TFtpClient(QObject *parent): QObject(parent), socket(new QUdpSocket(this))
{connect(socket, &QUdpSocket::readyRead,this, &TFtpClient::readPendingDatagrams);connect(socket, &QUdpSocket::connected,this, &TFtpClient::connected);connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(connectError(QAbstractSocket::SocketError)));
}void TFtpClient::setHostPort(QString const& host, quint16 port)
{host_ = host;port_ = port;
}void TFtpClient::getFile(QString const& localFileName, QString const& remoteFileName)
{isPut_ = false;localFileName_ = localFileName;remoteFileName_ = remoteFileName;socket->connectToHost(host_, port_);
}void TFtpClient::putFile(QString const& localFileName, QString const& remoteFileName)
{isPut_ = true;localFileName_ = localFileName;remoteFileName_ = remoteFileName;socket->connectToHost(host_, port_);
}void TFtpClient::stopFileTransfer()
{socket->disconnectFromHost();
}void TFtpClient::connected()
{ClientSocket* udp = new ClientSocket(socket);tftpFile_ = TFtpClientFile::Ptr(new TFtpClientFile(udp));bool isOK = true;if(isPut_)isOK = tftpFile_->putFile(localFileName_.toStdString(),remoteFileName_.toStdString(), TFtp::BINARY);elseisOK = tftpFile_->getFile(localFileName_.toStdString(),remoteFileName_.toStdString(), TFtp::BINARY);if(!isOK)emit error("Local File not Found");elseemit started();
}void TFtpClient::connectError(QAbstractSocket::SocketError)
{emit error("Connect host is failed");
}void TFtpClient::readPendingDatagrams()
{while (socket->hasPendingDatagrams()) {QNetworkDatagram datagram = socket->receiveDatagram();QByteArray d = datagram.data();if(tftpFile_){tftpFile_->process((uint8_t *)d.data(), d.size());emit progress(tftpFile_->file_bytes(), tftpFile_->filesize());if(tftpFile_->is_finished()){if(tftpFile_->is_error())emit error(QString::fromStdString(tftpFile_->error_msg()));elseemit finished();}}}
}TFtpClientWidget::TFtpClientWidget(QWidget *parent): QWidget(parent), ui(new Ui::TFtpClientWidget), tftpClient(new TFtpClient(this))
{ui->setupUi(this);connect(ui->btnBrowse, SIGNAL(clicked()), this, SLOT(onSelectLocalFile()));connect(ui->btnGet, SIGNAL(clicked()), this, SLOT(onGetFile()));connect(ui->btnPut, SIGNAL(clicked()), this, SLOT(onPutFile()));connect(ui->btnBreak, SIGNAL(clicked()), this, SLOT(onStop()));connect(tftpClient, &TFtpClient::started, this, &TFtpClientWidget::onStarted);connect(tftpClient, &TFtpClient::progress, this, &TFtpClientWidget::onProgress);connect(tftpClient, &TFtpClient::finished, this, &TFtpClientWidget::onFinished);connect(tftpClient, &TFtpClient::error, this, &TFtpClientWidget::onError);
}TFtpClientWidget::~TFtpClientWidget()
{delete ui;
}void TFtpClientWidget::onGetFile()
{tftpClient->stopFileTransfer();tftpClient->setHostPort(ui->lineEditHost->text(), ui->spinBoxPort->value());tftpClient->getFile(ui->lineEditLocalFile->text(), ui->lineEditRemoteFile->text());ui->progressBar->setValue(0);
}void TFtpClientWidget::onPutFile()
{tftpClient->stopFileTransfer();tftpClient->setHostPort(ui->lineEditHost->text(), ui->spinBoxPort->value());tftpClient->putFile(ui->lineEditLocalFile->text(), ui->lineEditRemoteFile->text());ui->progressBar->setValue(0);
}void TFtpClientWidget::onStarted()
{enableButtons(false);
}void TFtpClientWidget::onProgress(quint64 bytes, quint64 total)
{if(total > 0)ui->progressBar->setValue(bytes * 100 / total);else{int value = ui->progressBar->value();ui->progressBar->setValue(QRandomGenerator(value).bounded(value, 99));}
}void TFtpClientWidget::onStop()
{enableButtons(true);tftpClient->stopFileTransfer();
}void TFtpClientWidget::onFinished()
{if(tftpClient->isPut())QMessageBox::information(this, "TFtpClient", "Put is done!");elseQMessageBox::information(this, "TFtpClient", "Get is done!");enableButtons(true);
}void TFtpClientWidget::onError(QString const& error)
{QMessageBox::critical(this, "TFtpClient", error);enableButtons(true);
}void TFtpClientWidget::onSelectLocalFile()
{static QString filePath;QFileDialog dialog(this, tr("Select File"), filePath, tr("All files (*.*)"));if(dialog.exec() == QDialog::Rejected)return;QStringList fileNames = dialog.selectedFiles();if(fileNames.isEmpty())return;QString fileName = fileNames.first();filePath = QFileInfo(fileName).filePath();ui->lineEditLocalFile->setText(fileName);
}void TFtpClientWidget::enableButtons(bool enable)
{ui->btnGet->setEnabled(enable);ui->btnPut->setEnabled(enable);ui->btnBreak->setDisabled(enable);
}

3.TFTP Server

3.1 界面

在这里插入图片描述

3.2 源码

uint32_t ServerSocket::write(const char* data, size_t size)
{return socket_->writeDatagram(data, size, host_, port_);
}TFtpServer::TFtpServer(QObject *parent): QObject(parent), socket(new QUdpSocket(this)), fileManager_(new TFtpFileManager())
{connect(socket, &QUdpSocket::readyRead,this, &TFtpServer::readPendingDatagrams);
}void TFtpServer::setFilePath(QString const& filePath)
{if(!filePath.endsWith("/"))filePath_ = filePath + "/";
}void TFtpServer::start()
{if(!socket->bind(TFTP_PORT))emit bindError();
}void TFtpServer::stop()
{socket->close();
}void TFtpServer::readPendingDatagrams()
{while (socket->hasPendingDatagrams()) {QNetworkDatagram datagram = socket->receiveDatagram();QByteArray d = datagram.data();QString  transferId = QString("%1:%2").arg(datagram.senderAddress().toString()).arg(datagram.senderPort());TFtpServerFile::Ptr file = fileManager_->find(transferId.toStdString());if(file)file->process((uint8_t *)d.data(), d.size());else{ServerSocket* udp = new ServerSocket(socket, datagram.senderAddress(), datagram.senderPort());file = TFtpServerFile::Ptr(new TFtpServerFile(udp, filePath_.toStdString(), transferId.toStdString()));fileManager_->add(file);file->process((uint8_t *)d.data(), d.size());emit startFile(transferId, QString::fromStdString(file->filename()));}if(!file->is_finished()){if(file->type() == TFtpServerFile::Read)emit statusText(QString("Downloding file: %1, progress: %4% blockNumber(%2/%3)").arg(QString::fromStdString(file->filename())).arg(file->block_number()).arg(file->block_numbers()).arg(file->block_number() * 100 / file->block_numbers()));elseemit statusText(QString("Uploading file: %1, blockNumber(%2)").arg(QString::fromStdString(file->filename())).arg(file->block_number()));emit progress(transferId, file->file_bytes(), file->filesize());}else{if(file->is_error())emit statusText(QString("%1:%2").arg((int)file->error()).arg(QString::fromStdString(file->error_msg())));elseemit statusText(QString());emit progress(transferId, file->file_bytes(), file->filesize());emit stopFile(transferId);fileManager_->remove(file->transfer_id());}}
}TFtpServerWidget::TFtpServerWidget(QWidget *parent): QWidget(parent), ui(new Ui::TFtpServerWidget), tftpServer(new TFtpServer(this))
{ui->setupUi(this);loadSettings();connect(ui->btnBrowse, SIGNAL(clicked()), this, SLOT(selectTFtpDir()));connect(ui->currentDir, SIGNAL(currentIndexChanged(QString)), this, SLOT(setCurrentDir(QString)));connect(tftpServer, SIGNAL(startFile(QString,QString)), this, SLOT(onStartFile(QString,QString)));connect(tftpServer, SIGNAL(progress(QString,quint64,quint64)), this, SLOT(onProgress(QString,quint64,quint64)));connect(tftpServer, SIGNAL(stopFile(QString)), this, SLOT(onStopFile(QString)));connect(tftpServer, SIGNAL(bindError()), this, SLOT(onBindError()));tftpServer->start();
}TFtpServerWidget::~TFtpServerWidget()
{saveSettinggs();tftpServer->stop();delete ui;
}void TFtpServerWidget::selectTFtpDir()
{QString filePath = QFileDialog::getExistingDirectory(this,"Select Dir", ui->currentDir->currentText());if(filePath.isEmpty())return;int index  = ui->currentDir->findText(filePath);if(index != -1)ui->currentDir->setCurrentIndex(index);else{if(ui->currentDir->count() >= MAX_PATH_SIZE)ui->currentDir->removeItem(0);ui->currentDir->addItem(filePath);ui->currentDir->setCurrentIndex(ui->currentDir->count()  - 1);}
}void TFtpServerWidget::setCurrentDir(QString const& path)
{tftpServer->setFilePath(path);
}void TFtpServerWidget::onStartFile(QString const&transferId, QString const& fileName)
{ui->clientTables->addTopLevelItem(new QTreeWidgetItem(QStringList()<< transferId << fileName << QTime::currentTime().toString("hh:mm:ss")));
}void TFtpServerWidget::onProgress(QString const&transferId, quint64 bytes, quint64 total)
{QList<QTreeWidgetItem*> items = ui->clientTables->findItems(transferId, Qt::MatchCaseSensitive);for(int i = 0; i < items.size(); i++){if(total == 0)items[i]->setText(5, QString::number(bytes));else{   items[i]->setText(3, QString("%1%").arg(bytes * 100 / total));items[i]->setText(5, QString::number(total));}items[i]->setText(4, QString::number(bytes));}
}void TFtpServerWidget::onStopFile(QString const&transferId)
{QList<QTreeWidgetItem*> items = ui->clientTables->findItems(transferId, Qt::MatchCaseSensitive);for(int i = 0; i < items.size(); i++){int index = ui->clientTables->indexOfTopLevelItem(items[i]);ui->clientTables->takeTopLevelItem(index);}
}void TFtpServerWidget::saveSettinggs()
{QSettings settings(QCoreApplication::applicationName(), QCoreApplication::applicationVersion());QStringList dirs;for(int i = 0; i < ui->currentDir->count(); i++)dirs << ui->currentDir->itemText(i);settings.setValue("dirs", dirs);settings.setValue("currentDir", ui->currentDir->currentText());
}void TFtpServerWidget::loadSettings()
{QSettings settings(QCoreApplication::applicationName(), QCoreApplication::applicationVersion());QStringList dirs = settings.value("dirs", QStringList()).toStringList();QString currentDir = settings.value("currentDir", QString()).toString();ui->currentDir->addItems(dirs);int index  = ui->currentDir->findText(currentDir);if(index != -1){tftpServer->setFilePath(currentDir);ui->currentDir->setCurrentIndex(index);}else{tftpServer->setFilePath(QApplication::applicationDirPath());ui->currentDir->addItem(QApplication::applicationDirPath());}
}void TFtpServerWidget::onBindError()
{QMessageBox::critical(this, "TFtpServer", "Port(69) is already occupied!");ui->btnBrowse->setDisabled(true);ui->currentDir->setDisabled(true);setWindowTitle("TFtpServer is not running");
}

4.工程链接

源码工程链接:https://download.csdn.net/download/weixin_43996145/90300559

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/6808.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dm8在Linux环境安装精简步骤说明(2024年12月更新版dm8)

dm8在Linux环境安装详细步骤 - - 2025年1月之后dm8 环境介绍1 修改操作系统资源限制2 操作系统创建用户3 操作系统配置4 数据库安装5 初始化数据库6 实例参数优化7 登录数据库配置归档与备份8 配置审计9 创建用户10 屏蔽关键字与数据库兼容模式11 jdbc连接串配置12 更多达梦数据…

24年总结 -- 共赴心中所向往的未来

一、前言 我又回来了&#xff0c;前阵子忙着期末考试的东西&#xff0c;也是快半个月没更新了&#xff0c;刚好前几天报名了博客之星的评选&#xff0c;也很幸运的入围了&#xff0c;也借此机会来回顾一下关于2024年的个人成长、创作经历等。 二、个人 本人是一个双非学校的软…

动态规划一> 让字符串成为回文串的最少插入次数

题目&#xff1a; 解析&#xff1a; 状态表示状态转移方程&#xff1a; 初始化填表顺序返回值&#xff1a; 代码&#xff1a; public int minInsertions(String ss) {char[] s ss.toCharArray();int n s.length; int[][] dp new int[n][n]; for(int i n-1; i > 0;…

2025.1.21——八、[HarekazeCTF2019]Avatar Uploader 2(未完成) 代码审计|文件上传

题目来源&#xff1a;buuctf [HarekazeCTF2019]Avatar Uploader 2 一、打开靶机&#xff0c;整理信息 跟Avatar Uploader 1 题目长得一样&#xff0c;先上传相同文件看看情况&#xff0c;另外这道题还有源码&#xff0c;可以看看 二、解题思路 step 1&#xff1a;上传同类…

Elementor Pro 3.27 汉化版 2100套模板 安装教程 wordpress主题中文编辑器插件免费下载

插件下载地址 https://a5.org.cn/a5ziyuan/732506.html 转载请注明出处! Elementor Pro 是流行的 Elementor 的付费扩展 WordPress 页面构建器插件. 它为免费的 Elementor 插件添加了许多附加功能和增强功能&#xff0c;使其成为创建美丽的更强大的工具 WordPress 网站。 如果…

深入理解动态规划(dp)--(提前要对dfs有了解)

前言&#xff1a;对于动态规划&#xff1a;该算法思维是在dfs基础上演化发展来的&#xff0c;所以我不想讲的是看到一个题怎样直接用动态规划来解决&#xff0c;而是说先用dfs搜索&#xff0c;一步步优化&#xff0c;这个过程叫做动态规划。&#xff08;该文章教你怎样一步步的…

0基础跟德姆(dom)一起学AI 自然语言处理19-输出部分实现

1 输出部分介绍 输出部分包含: 线性层softmax层 2 线性层的作用 通过对上一步的线性变化得到指定维度的输出, 也就是转换维度的作用. 3 softmax层的作用 使最后一维的向量中的数字缩放到0-1的概率值域内, 并满足他们的和为1. 3.1 线性层和softmax层的代码分析 # 解码器类…

uart iic spi三种总线的用法

1、uart串口通信 这种连接方式抗干扰能力弱&#xff0c;旁边有干扰源就会对收发的电平数据造成干扰&#xff0c;进而导致数据失真 这种连接方式一般适用于一块板子上面的两个芯片之间进行数据传输 &#xff0c;属于异步全双工模式。 1.空闲位&#xff1a;当不进行数据收发时&am…

类与对象(上)

面向过程和面向对象初步认识 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 C是基于面向对象的&#xff0c;关注的是对象&#xff0c;将一件事情拆分成不同的对象&#xff0c;靠对象之间的交互完成。 类的…

三元组抽取在实际应用中如何处理语义模糊性?

在实际应用中&#xff0c;三元组抽取面临语义模糊性的问题&#xff0c;这主要体现在输入文本的非规范描述、复杂句式以及多义性等方面。为了有效处理这种模糊性&#xff0c;研究者们提出了多种方法和技术&#xff0c;以下是一些关键策略&#xff1a; 基于深度学习的方法 深度学…

【线性代数】基础版本的高斯消元法

[精确算法] 高斯消元法求线性方程组 线性方程组 考虑线性方程组&#xff0c; 已知 A ∈ R n , n , b ∈ R n A\in \mathbb{R}^{n,n},b\in \mathbb{R}^n A∈Rn,n,b∈Rn&#xff0c; 求未知 x ∈ R n x\in \mathbb{R}^n x∈Rn A 1 , 1 x 1 A 1 , 2 x 2 ⋯ A 1 , n x n b 1…

智慧脚下生根,智能井盖监测终端引领城市安全新革命

在繁忙的都市生活中&#xff0c;我们往往只关注地面的繁华与喧嚣&#xff0c;却忽略了隐藏在地面之下的基础设施——井盖。这些看似不起眼的井盖&#xff0c;实则承担着排水、通讯、电力等重要功能&#xff0c;是城市安全运转的重要一环。然而&#xff0c;传统的井盖管理面临着…

如何快速开发LabVIEW项目,成为LabVIEW开发的高手

发现了一篇多年前写的文章&#xff0c;转发到这里 如何快速开发LabVIEW项目&#xff0c;成为LabVIEW开发的高手。 如果您手里有LabVIEW项目&#xff0c;领导催的又很紧&#xff0c;该怎么办&#xff1f; 如果您公司规模小&#xff0c;就想把LabVIEW项目快速搞定&#xff0c;有什…

Zemax 非序列模式下的颜色检测器和颜色混合

在 Zemax 的非序列模式中&#xff0c;探测器用于捕获系统中射线的信息。可以使用各种类型的探测器来捕获光学系统性能的不同方面&#xff0c;例如矩形探测器&#xff0c;它存储撞击它的 NSC 源射线的能量数据。 另一种经常使用的探测器类型是 Detector Color&#xff0c;它是一…

Redis(5,jedis和spring)

在前面的学习中&#xff0c;只是学习了各种redis的操作&#xff0c;都是在redis命令行客户端操作的&#xff0c;手动执行的&#xff0c;更多的时候就是使用redis的api&#xff08;&#xff09;&#xff0c;进一步操作redis程序。 在java中实现的redis客户端有很多&#xff0c;…

AAAI2024论文解读|HGPROMPT Bridging Homogeneous and Heterogeneous Graphs

论文标题 HGPROMPT: Bridging Homogeneous and Heterogeneous Graphs for Few-shot Prompt Learning 跨同构异构图的小样本提示学习 论文链接 HGPROMPT: Bridging Homogeneous and Heterogeneous Graphs for Few-shot Prompt Learning论文下载 论文作者 Xingtong Yu, Yuan…

闲鱼自动抓取/筛选/发送系统

可监控闲鱼最新发布商品&#xff0c;发送钉钉 1&#xff0c;精准关键词匹配&#xff1a;输入核心关键词&#xff0c;精准定位与之高度契合的信息&#xff0c;确保搜索结果直击要点&#xff0c;满足您对特定内容的急切需求。 2&#xff0c;标题关键词智能筛选&#xff1a;不仅着…

AI编程工具使用技巧:在Visual Studio Code中高效利用阿里云通义灵码

AI编程工具使用技巧&#xff1a;在Visual Studio Code中高效利用阿里云通义灵码 前言一、通义灵码介绍1.1 通义灵码简介1.2 主要功能1.3 版本选择1.4 支持环境 二、Visual Studio Code介绍1.1 VS Code简介1.2 主要特点 三、安装VsCode3.1下载VsCode3.2.安装VsCode3.3 打开VsCod…

【Unity3D】Unity混淆工具Obfuscator使用

目录 一、导入工具 二、各种混淆形式介绍 2.1 程序集混淆 2.2 命名空间混淆 2.3 类混淆 2.4 函数混淆 2.5 参数混淆 2.6 字段混淆 2.7 属性混淆 2.8 事件混淆 三、安全混淆 四、兼容性处理 4.1 动画方法兼容 4.2 GUI方法兼容 4.3 协程方法兼容 五、选项 5.1 调…

2024年终总结:技术成长与突破之路

文章目录 前言一、技术成长&#xff1a;菜鸟成长之路1. 学习与实践的结合2. 技术分享与社区交流 二、生活与事业的平衡&#xff1a;技术之外的思考1. 时间管理与效率提升2. 技术对生活的积极影响 三、突破与展望&#xff1a;未来之路1. 技术领域的突破2. 未来规划与目标 四、结…