Qt实现TCP文件传输例子
来源:互联网 发布:yum install CMake 编辑:程序博客网 时间:2024/06/05 09:10
- 参考
- 效果
- Notes
- 主要代码
- 发送端
- mainwindowh
- mainwindowcpp
- 接收端
- receivefileh
- receivefilecpp
- 发送端
- 完整代码
参考
第38篇 网络(八)TCP(二)
QT TCP socket通信(二)
效果
- 发送端
- 标签,提示状态信息
- 进度条,提示发送进度
- 选择按钮,单击弹出选文件对话框
- 发送按钮,单击开始发送
- 接收端
- 标签,提示状态信息
- 进度条,提示发送进度
- 监听按钮,单击开始监听端口
- 效果图
- 工程截图
- 运行效果
- 工程截图
Notes
- 发送端取消按钮未实现,忽略…
- socket 向链接成功发送数据后,会发出
bytesWritten(qint64)
信号 - QDataStream 设置版本(
setVersion()
)时,发送端和接收端要设置成同一版本
主要代码
发送端
mainwindow.h
#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QMainWindow>#include <QAbstractSocket>class QByteArray;class QFile;class QString;class QTcpSocket;namespace Ui { class MainWindow;}class MainWindow : public QMainWindow{ Q_OBJECTpublic: explicit MainWindow(QWidget *parent = 0); ~MainWindow();private slots: void start_transfer(); void continue_transfer(qint64); void show_error(QAbstractSocket::SocketError); void on_selectBtn_clicked(); void on_sendBtn_clicked();private: Ui::MainWindow *ui; QTcpSocket *send; QFile *file; QString fileName; /* 总数据大小,已发送数据大小,剩余数据大小,每次发送数据块大小 */ qint64 fileBytes, sentBytes, restBytes, loadBytes;};#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"#include "ui_mainwindow.h"#include <QByteArray>#include <QDataStream>#include <QFileDialog>#include <QHostAddress>#include <QIODevice>#include <QString>#include <QTcpSocket>const quint16 PORT = 3333;const qint64 LOADBYTES = 4 * 1024; // 4 kilo-byteconst int DATA_STREAM_VERSION = QDataStream::Qt_5_8;MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){ ui->setupUi(this); send = new QTcpSocket(this); fileBytes = sentBytes = restBytes = 0; loadBytes = LOADBYTES; file = Q_NULLPTR; ui->sendProg->setValue(0); // 进度条置零 ui->sendBtn->setEnabled(false); // 禁用发送按钮 ui->cancelBtn->setEnabled(false); /* 连接已建立 -> 开始发数据 */ connect(send, SIGNAL(connected()), this, SLOT(start_transfer())); /* 数据已发出 -> 继续发 */ connect(send, SIGNAL(bytesWritten(qint64)), this, SLOT(continue_transfer(qint64))); /* socket出错 -> 错误处理 */ connect(send, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(show_error(QAbstractSocket::SocketError)));}MainWindow::~MainWindow(){ delete ui; delete send;}/*--- 点击选择按钮 ---*/void MainWindow::on_selectBtn_clicked(){ /* 开文件选择窗选文件,返回带路径文件名 */ fileName = QFileDialog::getOpenFileName(this); if(!fileName.isEmpty()) { ui->stLabel->setText( QString("File %1 Opened!").arg(fileName)); ui->sendBtn->setEnabled(true); } else ui->stLabel->setText(QString("*** FAIL OPENING FILE"));}/*--- 点击发送按钮 ---*/void MainWindow::on_sendBtn_clicked(){ /* 发送连接请求 */ send->connectToHost(QHostAddress::LocalHost, PORT); sentBytes = 0; ui->sendBtn->setEnabled(false); ui->cancelBtn->setEnabled(true); ui->stLabel->setText(QString("Linking..."));}/*--- 开始传送 ---*/void MainWindow::start_transfer(){ file = new QFile(fileName); if(!file->open(QFile::ReadOnly)) { ui->stLabel->setText(QString("*** FILE OPEN ERROR")); qDebug() << "*** start_transfer(): File-Open-Error"; return; } fileBytes = file->size(); ui->sendProg->setValue(0); ui->stLabel->setText(QString("Connection Established!")); QByteArray buf; QDataStream out(&buf, QIODevice::WriteOnly); out.setVersion(DATA_STREAM_VERSION); /* 无路径文件名 */ QString sfName = fileName.right(fileName.size() - fileName.lastIndexOf('/') - 1); /* 首部 = 总大小 + 文件名长度 + 文件名 */ out << qint64(0) << qint64(0) << sfName; /* 总大小加上首部的大小 */ fileBytes += buf.size(); ui->sendProg->setMaximum(fileBytes); /* 重写首部的前两个长度字段 */ out.device()->seek(0); out << fileBytes << (qint64(buf.size()) - 2 * sizeof(qint64)); /* 发送首部,计算剩余大小 */ restBytes = fileBytes - send->write(buf);}/*--- 继续传输 ---*/void MainWindow::continue_transfer(qint64 sentSize){ sentBytes += sentSize; ui->sendProg->setValue(sentBytes); /* 还有数据要发 */ if(restBytes > 0) { /* 从文件读数据 */ QByteArray buf = file->read(qMin(loadBytes, restBytes)); /* 发送 */ restBytes -= send->write(buf); } else file->close(); /* 全部发送完 */ if(sentBytes == fileBytes) { send->close(); // 关socket fileName.clear(); // 清空文件名 ui->stLabel->setText(QString("Finish sending!")); }}/*--- 出错处理 ---*/void MainWindow::show_error(QAbstractSocket::SocketError){ qDebug() << "*** Socket Error"; send->close(); ui->stLabel->setText(QString("*** SOCKET ERROR, RESEND LATER")); ui->sendBtn->setEnabled(true); ui->sendProg->reset(); // 进度条归零 fileName.clear();}
接收端
receivefile.h
#ifndef RECEVIEFILE_H#define RECEVIEFILE_H#include <QMainWindow>#include <QAbstractSocket>class QFile;class QString;class QTcpServer;class QTcpSocket;namespace Ui { class RecevieFile;}class RecevieFile : public QMainWindow{ Q_OBJECTpublic: explicit RecevieFile(QWidget *parent = 0); ~RecevieFile();private slots: void accept_connect(); void recevie_file(); void show_error(QAbstractSocket::SocketError); void on_listenBtn_clicked();private: Ui::RecevieFile *ui; QTcpServer *server; QTcpSocket *receive; QString fileName; QFile *file; /* 已接受数据,总数据,文件名长度 */ qint64 gotBytes, fileBytes, nameSize;};#endif // RECEVIEFILE_H
receivefile.cpp
#include "receviefile.h"#include "ui_receviefile.h"#include <iostream>#include <QDataStream>#include <QFile>#include <QHostAddress>#include <QTcpServer>#include <QTcpSocket>const quint16 PORT = 3333;const int DATA_STREAM_VERSION = QDataStream::Qt_5_8;RecevieFile::RecevieFile(QWidget *parent) : QMainWindow(parent), ui(new Ui::RecevieFile){ ui->setupUi(this); /* 进度条调零 */ ui->recvProg->setValue(0); /* 启用监听按钮 */ ui->listenBtn->setEnabled(true); fileBytes = gotBytes = nameSize = 0; file = Q_NULLPTR; receive = Q_NULLPTR; server = new QTcpServer(this); /* 连接请求 -> 接受连接 */ connect(server, SIGNAL(newConnection()), this, SLOT(accept_connect()));}RecevieFile::~RecevieFile(){ delete ui; delete server;}/*--- 点击监听按钮 ---*/void RecevieFile::on_listenBtn_clicked(){ /* 禁用监听按钮 */ ui->listenBtn->setEnabled(false); if(!server->listen(QHostAddress::Any, PORT)) { std::cerr << "*** Listen to Port Failed ***" << std::endl; qDebug() << server->errorString(); close(); ui->listenBtn->setEnabled(false); return; } ui->stLabel->setText(QString("Listing to Port %1").arg(PORT));}/*--- 接受连接请求 ---*/void RecevieFile::accept_connect(){ receive = server->nextPendingConnection(); /* 有数据到 -> 接受数据 */ connect(receive, SIGNAL(readyRead()), this, SLOT(recevie_file())); /* socket出错 -> 出错处理 */ connect(receive, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(show_error(QAbstractSocket::SocketError))); ui->stLabel->setText(QString("Connection Established!")); gotBytes = 0; server->close();}/*--- 接收文件 ---*/void RecevieFile::recevie_file(){ QDataStream in(receive); in.setVersion(DATA_STREAM_VERSION); /* 首部未接收/未接收完 */ if(gotBytes <= 2 * sizeof(qint64)) { if(!nameSize) // 前两个长度字段未接收 { if(receive->bytesAvailable() >= 2 * sizeof(qint64)) { in >> fileBytes >> nameSize; gotBytes += 2 * sizeof(qint64); ui->recvProg->setMaximum(fileBytes); ui->recvProg->setValue(gotBytes); } else // 数据不足,等下次 return; } else if(receive->bytesAvailable() >= nameSize) { in >> fileName; gotBytes += nameSize; ui->recvProg->setValue(gotBytes); std::cout << "--- File Name: " << fileName.toStdString() << std::endl; } else // 数据不足文件名长度,等下次 return; } /* 已读文件名、文件未打开 -> 尝试打开文件 */ if(!fileName.isEmpty() && file == Q_NULLPTR) { file = new QFile(fileName); if(!file->open(QFile::WriteOnly)) // 打开失败 { std::cerr << "*** File Open Failed ***" << std::endl; delete file; file = Q_NULLPTR; return; } ui->stLabel->setText(QString("Open %1 Successfully!").arg(fileName)); } if(file == Q_NULLPTR) // 文件未打开,不能进行后续操作 return; if(gotBytes < fileBytes) // 文件未接收完 { gotBytes += receive->bytesAvailable(); ui->recvProg->setValue(gotBytes); file->write(receive->readAll()); } if(gotBytes == fileBytes) // 文件接收完 { receive->close(); // 关socket file->close(); // 关文件 delete file; ui->stLabel->setText(QString("Finish receiving %1").arg(fileName)); ui->listenBtn->setEnabled(true); }}/*--- 出错处理 ---*/void RecevieFile::show_error(QAbstractSocket::SocketError){ std::cerr << "*** Socket Error ***" << std::endl; qDebug() << receive->errorString(); receive->close(); // 关cocket receive = Q_NULLPTR; file = Q_NULLPTR; fileName.clear(); // 清空文件名 fileBytes = gotBytes = nameSize = 0; ui->recvProg->reset(); // 进度条归零 ui->listenBtn->setEnabled(true); // 启用监听按钮 ui->stLabel->setText(QString("*** SOCKET ERROR"));}
完整代码
Qt实现TCP文件传输例子
阅读全文
0 0
- Qt实现TCP文件传输例子
- Qt TCP文件传输
- qt+boost::asio+tcp文件传输
- qt+boost--asio+tcp文件传输
- TCP协议实现文件传输
- TCP协议实现文件传输
- TCP实现文件传输
- TCP协议实现文件传输
- TCP协议实现文件传输
- 在QT实现文件传输
- 使用TCP协议实现文件传输
- Qt:基于TCP的多线程文件传输工具
- TCP/IP编程实现远程文件传输
- TCP/IP编程实现远程文件传输
- TCP/IP编程实现远程文件传输
- TCP/IP编程实现远程文件传输
- TCP/IP编程实现远程文件传输
- TCP/IP编程实现远程文件传输
- 算法导论:堆排序
- opencv2.4.13+vs2013
- 39. OP-TEE中secure stroage------安全文件数据的打开过程(open)
- linux上安装免安装版MySQL5.7.18
- OGNL和Struts2中的值栈
- Qt实现TCP文件传输例子
- iTerm2的个人使用
- 属性计算
- 理解Java内存模型总结
- 【Java基础】多线程之synchronized
- OpenCV自学笔记6. 图像分割
- struts2 result 类型
- 关于One-hot编码
- 欢迎使用CSDN-markdown编辑器