首选预览一下最终实现的效果,如下图:
一、服务器端
1、widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QTcpServer> //监听套接字 #include <QTcpSocket> //通信套接字 #include <QFile> #include <QTimer> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); void sendData(); //发送文件数据 private slots: void on_buttonFile_clicked(); void on_buttonSend_clicked(); private: Ui::Widget *ui; QTcpServer *tcpServer; //监听套接字 QTcpSocket *tcpSocket; //通信套接字 QFile file; //文件对象 QString fileName; //文件名称 quint64 fileSize; //文件大小 quint64 sendSize; //已经发送文件大小 QTimer timer; //定时器 }; #endif // WIDGET_H
2、widget.cpp
#include "widget.h" #include "ui_widget.h" #include <QHostAddress> #include <QFileDialog> #include <QMessageBox> #include <QFileInfo> #include <QDebug> Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); setWindowTitle("服务器端口:8899"); //禁用两个按钮 ui->buttonFile->setEnabled(false); ui->buttonSend->setEnabled(false); //监听套接字 tcpServer = new QTcpServer(this); //监听 tcpServer->listen(QHostAddress::Any, 8899); //如果客户端成功与服务器连接 //tcpServer会自动触发newConnection connect(tcpServer, &QTcpServer::newConnection, [=](){ //取出建立好连接的套接字 tcpSocket = tcpServer->nextPendingConnection(); //获取对方的ip和端口 QString ip = tcpSocket->peerAddress().toString(); quint16 port = tcpSocket->peerPort(); //组包 QString str = QString("[%1:%2] 成功连接").arg(ip).arg(port); ui->textEdit->setText(str); //成功连接后才能选择文件 ui->buttonFile->setEnabled(true); }); connect(&timer, &QTimer::timeout, [=](){ //关闭定时器 timer.stop(); //发送文件 sendData(); }); } Widget::~Widget() { delete ui; } //选择文件 void Widget::on_buttonFile_clicked() { QString filePath = QFileDialog::getOpenFileName(this,"选择文件","../"); //如果选择文件路径无效则提示 if(filePath.isEmpty()){ QMessageBox::information(this, "提示", filePath+"文件路径无效"); return ; } fileName.clear(); fileSize = 0; sendSize = 0; //获取文件信息 QFileInfo info(filePath); fileName = info.fileName(); //获取文件名字 fileSize = info.size(); //获取文件大小 //以只读方式打开 //指定文件的名称 file.setFileName(filePath); //打开文件 bool isOk = file.open(QIODevice::ReadOnly); if(!isOk){ QMessageBox::information(this, "提示","只读方式打开文件失败"); return ; } //提示打开文件的路径 ui->textEdit->append(filePath); ui->buttonFile->setEnabled(false); ui->buttonSend->setEnabled(true); } //发送文件 void Widget::on_buttonSend_clicked() { //先发送文件头信息 文件名##文件大小 QString head = QString("%1##%2").arg(fileName).arg(fileSize); //发送头部信息 qint64 len = tcpSocket->write(head.toUtf8()); //如果len大于0,则头部信息发送成功 if(len > 0){ //发送真正 的文件信息 //防止tcp黏包信息 //需要通过定时器延时20毫秒 timer.start(20); }else{ QMessageBox::information(this, "提示","头部信息发送失败"); file.close(); ui->buttonFile->setEnabled(true); ui->buttonSend->setEnabled(false); return ; } } // 发送文件数据 void Widget::sendData() { ui->buttonFile->setEnabled(false); ui->buttonSend->setEnabled(false); quint64 len = 0; do{ //每次发送数据的大小 char buf[1024] = {0}; len = 0; //往文件中读数据 len = file.read(buf,sizeof(buf)); //发送数据,读多少,发多少 len = tcpSocket->write(buf,len); //发送的数据要累加 sendSize += len; }while(len > 0); //判断是否发送文件完毕 /*if(sendSize == fileSize){ QMessageBox::information(this, "提示","文件发送完毕"); ui->textEdit->append("文件发送完毕"); file.close(); //把客户端断开 tcpSocket->disconnectFromHost(); ui->buttonFile->setEnabled(true); ui->buttonSend->setEnabled(false); return ; }*/ }
二、客户端
1、clientwidget.h
#ifndef CLIENTWIDGET_H #define CLIENTWIDGET_H #include <QWidget> #include <QTcpSocket> #include <QFile> namespace Ui { class ClientWidget; } class ClientWidget : public QWidget { Q_OBJECT public: explicit ClientWidget(QWidget *parent = 0); ~ClientWidget(); private slots: void on_buttonConnect_clicked(); private: Ui::ClientWidget *ui; QTcpSocket *tcpSocket; QFile file; //文件对象 QString fileName; //文件名称 quint64 fileSize; //文件大小 quint64 reciveSize; //已经接收文件大小 bool isStart; }; #endif // CLIENTWIDGET_H
2、clientwidget.cpp
#include "clientwidget.h" #include "ui_clientwidget.h" #include <QMessageBox> #include <QHostAddress> ClientWidget::ClientWidget(QWidget *parent) : QWidget(parent), ui(new Ui::ClientWidget) { ui->setupUi(this); setWindowTitle("客户端"); ui->progressBar->setValue(0); isStart = true; tcpSocket = new QTcpSocket(this); connect(tcpSocket, &QTcpSocket::readyRead,[=](){ //取现接收的内容 QByteArray buf = tcpSocket->readAll(); if(isStart == true){ isStart = false; //解析问部信息 buf = "hello##1024" //QString str = "hello##1024"; str.section("##",0,0); //初始化 fileName = QString(buf).section("##",0,0); fileSize = QString(buf).section("##",1,1).toInt(); reciveSize = 0; //打开文件 file.setFileName("../"+fileName); bool isOk = file.open(QIODevice::WriteOnly|QIODevice::Append); if(isOk == false){ tcpSocket->disconnectFromHost(); tcpSocket->close(); QMessageBox::information(this, "提示", "打出文件出错"); return ; } //禁用连接按钮 ui->buttonConnect->setEnabled(false); //初始化进度条 ui->progressBar->setMinimum(0); ui->progressBar->setMaximum(fileSize/1024); ui->progressBar->setValue(0); }else{ //文件信息 quint64 len = file.write(buf); if(len > 0){ reciveSize += len; } //更新进度条 ui->progressBar->setValue(reciveSize/1024); if(reciveSize == fileSize){ //传输完毕后关闭文件 file.close(); QMessageBox::information(this, "提示", "文件接收完毕"); ui->buttonConnect->setEnabled(true); tcpSocket->disconnectFromHost(); tcpSocket->close(); } } }); } ClientWidget::~ClientWidget() { delete ui; } //连接服务器 void ClientWidget::on_buttonConnect_clicked() { //获取服务器的IP和端口 QString ip = ui->lineEditIp->text(); quint16 port = ui->lineEditPort->text().toInt(); //连接服务器 tcpSocket->connectToHost(QHostAddress(ip),port); ui->progressBar->setValue(0); }
版权声明:
此文为本站源创文章[或由本站编辑从网络整理改编],
转载请备注出处:
[狂码一生]
https://www.sindsun.com/articles/16/87
[若此文确切存在侵权,请联系本站管理员进行删除!]
--THE END--