Qt实现文件传输服务器
- 1、前言
- 2、服务器
- 2.1 服务器UI界面
- 2.2添加网络模块和头文件
- 2.3、创建服务器对象
- 2.4 连接有新连接的信号与槽
- 2.5实现有新连接处理的槽函数
- 2.6 选择文件按钮实现
- 2.6.1 连接按钮点击的信号与槽
- 2.6.2 添加头文件
- 2.6.3 创建所需对象
- 2.6.3 选择文件按钮实现
- 2.7 发送文件按钮实现
- 2.7.1添加定时器解决粘包问题
- 2.7.2 连接定时器结束信号与槽
- 2.7.3定时器结束槽函数实现
- 3、头文件和.cpp文件
-
- 4、总结
1、前言
记录自己对于Qt实现文件传输的学习过程,方便自己日后回顾,也可以给别人提供参考借鉴,目录就是实现的过程,大家可以按照目录逐步浏览,也可以点击目录跳转到所需部分,这个是服务器端,客户端在主页另外一篇博客。 |
2、服务器
2.1 服务器UI界面

2.2添加网络模块和头文件

#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>

2.3、创建服务器对象
#define PORT 8000 QTcpServer *tcpServer;
QTcpSocket *tcpSocket;


tcpServer = new QTcpServer(this);
tcpServer->listen(QHostAddress::Any,PORT);

2.4 连接有新连接的信号与槽
private slots:void newConnectionHandler();
connect(tcpServer,&QTcpServer::newConnection,this,&Widget::newConnectionHandler);
2.5实现有新连接处理的槽函数

ui->selectPushButton->setEnabled(false);
ui->sendPushButton->setEnabled(false);

void Widget::newConnectionHandler()
{tcpSocket = tcpServer->nextPendingConnection(); QString ip = tcpSocket->peerAddress().toString(); qint16 Port = tcpSocket->peerPort(); ui->ipLineEdit->setText(ip); ui->portLineEdit->setText(QString::number(Port)); QString connectTemp = QString("[%1:%2] 已连接").arg(ip).arg(Port); ui->messageTextEdit->setText(connectTemp); ui->selectPushButton->setEnabled(true); ui->sendPushButton->setEnabled(true);
}
2.6 选择文件按钮实现
2.6.1 连接按钮点击的信号与槽


2.6.2 添加头文件

添加QMessageBox是为了弹窗消息框,添加QDebug是为了打印信息 |
2.6.3 创建所需对象
QFile file; QString fileName;
qint64 fileSize;
qint64 senddFileSize;

2.6.3 选择文件按钮实现
void Widget::on_selectPushButton_clicked()
{QString filePath = QFileDialog::getOpenFileName(this,"open","../"); if(!filePath.isEmpty()){QFileInfo fileInfo(filePath); fileName = fileInfo.fileName(); fileSize = fileInfo.size(); senddFileSize = 0; file.setFileName(filePath); bool fileisOk = file.open(QIODevice::ReadOnly); if(fileisOk==false){QMessageBox::warning(this,"打开文件","打开文件失败"); }ui->messageTextEdit->setText(filePath); ui->selectPushButton->setEnabled(false); ui->sendPushButton->setEnabled(true); }else{QMessageBox::warning(this,"打开文件失败","文件不能为空"); }}
2.7 发送文件按钮实现
2.7.1添加定时器解决粘包问题

QTimer sendFileTimer;
2.7.2 连接定时器结束信号与槽
void sendFileTimeoutHandler();
sendFileTimer = new QTimer(this);
connect(sendFileTimer,&QTimer::timeout,this,&Widget::sendFileTimeoutHandler);
2.7.3定时器结束槽函数实现
void Widget::sendFileTimeoutHandler()
{sendFileTimer->stop(); char buf[4*1024] = {0}; qint64 bytesRead = file.read(buf, sizeof(buf)); if(bytesRead>0){qint64 bytesWritten = tcpSocket->write(buf, bytesRead); if (bytesWritten == -1) {QMessageBox::warning(this, "错误", "发送失败");return;}senddFileSize += bytesWritten; if (senddFileSize < fileSize) {sendFileTimer->start(20); } else {QMessageBox::information(this, "完成", "文件发送完毕");file.close();}}else if(senddFileSize < fileSize){QMessageBox::warning(this, "错误", "文件读取失败");}
}
3、头文件和.cpp文件
3.1 Widget.h文件
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QFileDialog>
#include <QFileInfo>
#include <QFile>
#include <QMessageBox>
#include <QDebug>
#include <QTimer>#define PORT 8000 QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void newConnectionHandler(); void sendFileTimeoutHandler(); void on_selectPushButton_clicked(); void on_sendPushButton_clicked(); private:Ui::Widget *ui;QTcpServer *tcpServer; QTcpSocket *tcpSocket; QFile file; QString fileName; qint64 fileSize; qint64 senddFileSize; QTimer *sendFileTimer;
};
#endif
3.2 .cpp文件
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);
ui->selectPushButton->setEnabled(false); ui->sendPushButton->setEnabled(false); tcpServer = new QTcpServer(this); tcpServer->listen(QHostAddress::Any,PORT); sendFileTimer = new QTimer(this); connect(tcpServer,&QTcpServer::newConnection,this,&Widget::newConnectionHandler); connect(sendFileTimer,&QTimer::timeout,this,&Widget::sendFileTimeoutHandler);
}Widget::~Widget()
{delete ui;
}
void Widget::newConnectionHandler()
{tcpSocket = tcpServer->nextPendingConnection(); QString ip = tcpSocket->peerAddress().toString(); qint16 Port = tcpSocket->peerPort(); ui->ipLineEdit->setText(ip); ui->portLineEdit->setText(QString::number(Port)); QString connectTemp = QString("[%1:%2] 已连接").arg(ip).arg(Port); ui->messageTextEdit->setText(connectTemp); ui->selectPushButton->setEnabled(true); ui->sendPushButton->setEnabled(true); }
void Widget::sendFileTimeoutHandler()
{sendFileTimer->stop(); char buf[4*1024] = {0}; qint64 bytesRead = file.read(buf, sizeof(buf)); if(bytesRead>0){qint64 bytesWritten = tcpSocket->write(buf, bytesRead); if (bytesWritten == -1) {QMessageBox::warning(this, "错误", "发送失败");return;}senddFileSize += bytesWritten; if (senddFileSize < fileSize) {sendFileTimer->start(20); } else {QMessageBox::information(this, "完成", "文件发送完毕");file.close();}}else if(senddFileSize < fileSize){QMessageBox::warning(this, "错误", "文件读取失败");}
}
void Widget::on_selectPushButton_clicked()
{QString filePath = QFileDialog::getOpenFileName(this,"open","../"); if(!filePath.isEmpty()){QFileInfo fileInfo(filePath); fileName = fileInfo.fileName(); fileSize = fileInfo.size(); senddFileSize = 0; file.setFileName(filePath); bool fileisOk = file.open(QIODevice::ReadOnly); if(fileisOk==false){QMessageBox::warning(this,"打开文件","打开文件失败"); }ui->messageTextEdit->setText(filePath); ui->selectPushButton->setEnabled(false); ui->sendPushButton->setEnabled(true); }else{QMessageBox::warning(this,"打开文件失败","文件不能为空"); }}
void Widget::on_sendPushButton_clicked()
{QString fileMes = QString("%1##%2\n").arg(fileName).arg(fileSize); qint64 fileLength = tcpSocket->write(fileMes.toUtf8().data()); if(fileLength > 0){sendFileTimer->start(20); }else{QMessageBox::warning(this,"发送文件","发送文件失败"); file.close(); tcpSocket->disconnectFromHost(); tcpSocket->close(); }
}
4、总结
以上就是Qt实现文件传输服务器端的整个过程了,浏览过程中,如若发现错误,欢迎大
家指正,有问题的可以评论区留言或者私信。最后,如果大家觉得有所帮助,可以点一
下赞,谢谢大家!未来是未知的,愿大家保持冷静,继续前行! |