• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

QT5+TCP/IP多线程传输图片

武飞扬头像
HAPY77
帮助1

先上实现结果

学新通

一、概述

        QT中设计TCP/IP通信主要使用QTCPServer和QTCPSocket两个类,功能分为服务器端和客户端,服务器端负责接收图片,客户端发送图片。多线程设计主要有两种方法,一种是通过添加继承于QThread的类,并在此类中实现run()函数为主体业务逻辑。另一种是继承自Qobject的类中实现业务逻辑,实例化以后添加到子线程(使用movetothread()方法,子线程需要在主线程中独立创建)。线程之间通信最好使用信号与槽机制,或者使用指针传递地址,否则容易报出各种错误。

二、多线程设计两种方式

1.简易版本(可以实现的逻辑有限)

mainwindow.cpp

  1.  
    m_ser = new QTcpServer(this);//指定父对象在父对象析构时自动析构
  2.  
    m_sock = new QTcpSocket(this);
  3.  
    ...
  4.  
    connect(m_ser,&QTcpServer::newConnection,this,[=]()
  5.  
    {
  6.  
    //得到套接字对象
  7.  
    m_sock = m_ser->nextPendingConnection();
  8.  
    //实例化子线程对象
  9.  
    recvFile* subThread = new recvFile(m_sock);
  10.  
    subThread->start();//开启子线程
  11.  
     
  12.  
    }

recvfile.cpp

  1.  
     
  2.  
    recvFile::recvFile(QTcpSocket* tcp,QObject *parent) : QThread(parent)
  3.  
    {
  4.  
    tcpSocket = tcp;
  5.  
    }
  6.  
     
  7.  
     
  8.  
     
  9.  
    void recvFile::run()
  10.  
    {
  11.  
    //实现接收文件逻辑
  12.  
    }

2.全面版本

mainwindow.cpp

  1.  
    /*多线程相关对象的实例化*/
  2.  
    //创建线程对象
  3.  
    QThread *m_thread = new QThread;
  4.  
    //创建任务对象
  5.  
    SendFile* worker = new SendFile;
  6.  
    //任务对象移动到子线程中
  7.  
    worker->moveToThread(m_thread);//任务对象会在子线程中执行

 sendfile.cpp

  1.  
    SendFile::SendFile(QObject *parent) : QObject(parent)
  2.  
    {
  3.  
     
  4.  
    tcpSocket = new QTcpSocket;
  5.  
    ...
  6.  
     
  7.  
    }

三、代码实现

1.UI设计

服务器

学新通

客户端

学新通

2.服务器端代码实现

mainwindow.cpp

  1.  
    #include "mainwindow.h"
  2.  
    #include "ui_mainwindow.h"
  3.  
     
  4.  
    #include<recvfile.h>
  5.  
    #include<QMessageBox>
  6.  
    MainWindow::MainWindow(QWidget *parent)
  7.  
    : QMainWindow(parent)
  8.  
    , ui(new Ui::MainWindow)
  9.  
    {
  10.  
    ui->setupUi(this);
  11.  
    ui_Init();//初始化ui
  12.  
    m_ser = new QTcpServer(this);//指定父对象在父对象析构时自动析构
  13.  
    m_sock = new QTcpSocket(this);
  14.  
     
  15.  
    qDebug()<<"主线程地址为"<<QThread::currentThread();
  16.  
     
  17.  
     
  18.  
    //建立连接以后
  19.  
    connect(m_ser,&QTcpServer::newConnection,this,[=]()
  20.  
    {
  21.  
    //得到套接字对象
  22.  
    m_sock = m_ser->nextPendingConnection();
  23.  
    //实例化子线程对象
  24.  
    recvFile* subThread = new recvFile(m_sock);
  25.  
    subThread->start();//开启子线程
  26.  
    ui->startLisenBt->setEnabled(false);
  27.  
    ui->closeListenBt->setDisabled(false);
  28.  
    //子线程中接收到的头文件信息显示到接收区
  29.  
    connect(subThread,&recvFile::headReceived,this,[=](QString buf)
  30.  
    {
  31.  
    ui->recvEdit->append(buf);
  32.  
    });
  33.  
     
  34.  
    //接收文件过程中更新进度条
  35.  
    connect(subThread,&recvFile::receivingPercent,ui->progressBar,&QProgressBar::setValue);
  36.  
    //接收完毕以后在主线程进行显示
  37.  
    connect(subThread,&recvFile::fileReceived,this,[=](QString path)
  38.  
    {
  39.  
    ui->statusLabel->setText("文件接收完毕");
  40.  
    show_picture(path);
  41.  
    });
  42.  
    }
  43.  
    );
  44.  
     
  45.  
     
  46.  
     
  47.  
     
  48.  
    /*
  49.  
    //当连接断开时
  50.  
    connect(m_sock,&QTcpSocket::disconnected,this,[=]()
  51.  
    {
  52.  
    m_sock->close();
  53.  
    m_sock->deleteLater();
  54.  
    m_status->setPixmap(QPixmap(":/red.jpeg").scaled(20,20));
  55.  
    });
  56.  
    */
  57.  
     
  58.  
    }
  59.  
     
  60.  
    MainWindow::~MainWindow()
  61.  
    {
  62.  
    delete ui;
  63.  
    }
  64.  
     
  65.  
     
  66.  
    void MainWindow:: ui_Init()
  67.  
    {
  68.  
    ui->PortEdit->setText("30201");
  69.  
    setWindowTitle("服务器");
  70.  
    //监听按钮初始化
  71.  
    ui->closeListenBt->setDisabled(true);
  72.  
    //进度条初始化
  73.  
    ui->progressBar->setRange(0,100);
  74.  
    ui->progressBar->setValue(0);
  75.  
    //状态栏初始化
  76.  
    m_status = new QLabel;
  77.  
    m_status->setPixmap(QPixmap(":/red.jpeg").scaled(20,20));
  78.  
    ui->statusbar->addWidget(new QLabel("连接状态"));
  79.  
    ui->statusbar->addWidget(m_status);
  80.  
    }
  81.  
     
  82.  
    //开启监听
  83.  
    void MainWindow::on_startLisenBt_clicked()
  84.  
    {
  85.  
    unsigned short port = ui->PortEdit->text().toUInt();
  86.  
    m_ser->listen(QHostAddress::Any,port);//开启监听
  87.  
    ui->startLisenBt->setDisabled(true);
  88.  
    //如果已经开启监听
  89.  
    if(m_ser->isListening() == true)
  90.  
    {
  91.  
     
  92.  
    ui->statusLabel->setText("已经开启监听");
  93.  
    ui->closeListenBt->setEnabled(true);
  94.  
    ui->startLisenBt->setDisabled(true);
  95.  
    m_status->setPixmap(QPixmap(":/green.jpeg").scaled(20,20));
  96.  
    }
  97.  
    }
  98.  
     
  99.  
     
  100.  
     
  101.  
     
  102.  
    void MainWindow::on_sendTextBt_clicked()
  103.  
    {
  104.  
    QString msg = ui->SendEdit->toPlainText();
  105.  
    m_sock->write(msg.toUtf8());
  106.  
    }
  107.  
     
  108.  
     
  109.  
    /*打开指定路径照片并显示*/
  110.  
    void MainWindow::show_picture(QString &filepath)
  111.  
    {
  112.  
    if(image.load(filepath))//当图像文件导入以后
  113.  
    {
  114.  
    //显示图像
  115.  
    ui->picShow_Label->setPixmap(QPixmap::fromImage(image).scaled(ui->picShow_Label->size()));
  116.  
    }
  117.  
    }
  118.  
     
  119.  
    void MainWindow::on_closeListenBt_clicked()
  120.  
    {
  121.  
     
  122.  
    m_ser->close();
  123.  
    if(!m_ser->isListening())
  124.  
    {
  125.  
    ui->statusLabel->setText("服务器已关闭");
  126.  
    ui->startLisenBt->setEnabled(true);
  127.  
    ui->closeListenBt->setDisabled(true);
  128.  
    }
  129.  
    else{
  130.  
    QMessageBox::critical(this,"错误","服务器关闭失败");
  131.  
    }
  132.  
    }
学新通

 mainwindow.h

  1.  
    #ifndef MAINWINDOW_H
  2.  
    #define MAINWINDOW_H
  3.  
     
  4.  
    #include <QMainWindow>
  5.  
    #include<QTcpServer>
  6.  
    #include<QHostInfo>
  7.  
    #include <QTcpSocket>
  8.  
    #include<QLabel>
  9.  
    QT_BEGIN_NAMESPACE
  10.  
    namespace Ui { class MainWindow; }
  11.  
    QT_END_NAMESPACE
  12.  
     
  13.  
    class MainWindow : public QMainWindow
  14.  
    {
  15.  
    Q_OBJECT
  16.  
     
  17.  
    public:
  18.  
    MainWindow(QWidget *parent = nullptr);
  19.  
    ~MainWindow();
  20.  
     
  21.  
    private slots:
  22.  
    void on_startLisenBt_clicked();
  23.  
     
  24.  
    void on_sendTextBt_clicked();
  25.  
     
  26.  
    void on_closeListenBt_clicked();
  27.  
     
  28.  
    private:
  29.  
    Ui::MainWindow *ui;
  30.  
    QTcpServer* m_ser;
  31.  
    QTcpSocket* m_sock;
  32.  
    QImage image; //接收并显示的图片对象
  33.  
    QLabel* m_status;
  34.  
    void ui_Init();
  35.  
    void show_picture(QString &filepath);
  36.  
    };
  37.  
    #endif // MAINWINDOW_H
学新通

recvfile.cpp

  1.  
    #include "recvfile.h"
  2.  
    #include<QMessageBox>
  3.  
    recvFile::recvFile(QTcpSocket* tcp,QObject *parent) : QThread(parent)
  4.  
    {
  5.  
    tcpSocket = tcp;
  6.  
     
  7.  
     
  8.  
    }
  9.  
     
  10.  
    void recvFile::run()
  11.  
    {
  12.  
    qDebug()<<"子线程地址为"<<QThread::currentThread();
  13.  
    //初始化文件接收数据
  14.  
    fileName = "";
  15.  
    fileSize = 0;
  16.  
    recvSize = 0;
  17.  
    isFile = false;
  18.  
    connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(readyRead_Slot()));
  19.  
     
  20.  
    }
  21.  
    void recvFile::readyRead_Slot()
  22.  
    {
  23.  
    QByteArray buf = tcpSocket->readAll();//缓冲区
  24.  
    if(isFile==false)
  25.  
    {
  26.  
    /*先接收文件头*/
  27.  
    isFile = true;//下一轮接收时就接收文件本身
  28.  
    //文件名字
  29.  
    fileName = QString(buf).section("#", 1, 1);
  30.  
    //文件大小
  31.  
    fileSize = QString(buf).section("#", 2, 2).toInt();
  32.  
     
  33.  
    QString head ="文件名" fileName "\n" "文件大小" QString(buf).section("#", 2, 2);
  34.  
    //文件头信息接收到以后发送到主线程进行显示
  35.  
    emit headReceived(head);
  36.  
     
  37.  
    recvSize = 0;
  38.  
    file.setFileName(fileName);
  39.  
     
  40.  
    if(false == file.open(QIODevice::WriteOnly))
  41.  
    {
  42.  
    qDebug() <<"文件打开失败";
  43.  
    //初始化数据
  44.  
    fileName = "";
  45.  
    fileSize = 0;
  46.  
    recvSize = 0;
  47.  
    isFile = false;
  48.  
    //QMessageBox::warning(this, "警告", "创建文件失败");
  49.  
    return;
  50.  
    }
  51.  
     
  52.  
    }
  53.  
     
  54.  
    else//接收文件本身
  55.  
    {
  56.  
    //ui->receiveEdit->append(QString("正在接收文件%1").arg(fileName));
  57.  
    qint64 len = file.write(buf);
  58.  
    //qDebug() <<"正在接收文件";
  59.  
    recvSize = len;
  60.  
    percent = (100 * recvSize ) / fileSize;
  61.  
    emit receivingPercent(percent);
  62.  
    //qDebug() <<"接收的百分比"<<percent;
  63.  
    }
  64.  
    if(recvSize == fileSize)//如果接收数据长度和发送数据长度相等做接收后处理
  65.  
    {
  66.  
    QFileInfo info;
  67.  
     
  68.  
    //qDebug() <<"接收完毕";
  69.  
    file.close();
  70.  
    info = QFileInfo(file);
  71.  
    imgpath = info.filePath();
  72.  
    emit fileReceived(imgpath);
  73.  
    isFile = false;
  74.  
    }
  75.  
     
  76.  
    }
学新通

 recvfile.h

  1.  
    #ifndef RECVFILE_H
  2.  
    #define RECVFILE_H
  3.  
     
  4.  
    #include <QObject>
  5.  
    #include<QThread>
  6.  
    #include<QTcpSocket>
  7.  
    #include<QFile>
  8.  
    #include<QImage>
  9.  
    #include<QFileInfo>
  10.  
    class recvFile : public QThread
  11.  
    {
  12.  
    Q_OBJECT
  13.  
    public:
  14.  
    explicit recvFile(QTcpSocket* tcp,QObject *parent = nullptr);
  15.  
    private:
  16.  
    QTcpSocket *tcpSocket;
  17.  
    QFile file; //文件对象
  18.  
    QString fileName; //文件名字
  19.  
    qint64 fileSize; //文件大小
  20.  
    qint64 recvSize; //已接收文件的大小
  21.  
    bool isFile; //接收文件标志
  22.  
    bool alreadyReceive; //接收完成标志
  23.  
    QImage image; //接收并显示的图片对象
  24.  
    QString imgpath; //接收到图片的路径
  25.  
    int percent; //接收的比例
  26.  
    protected:
  27.  
    void run() override;
  28.  
    private slots:
  29.  
    void readyRead_Slot();//接收文件数据的槽函数
  30.  
    signals:
  31.  
    void headReceived(QString head);//文件头信息接收到以后发送到主线程的接收区显示
  32.  
    void fileReceived(QString path);//文件完全接收以后发送文件路径到主线程显示
  33.  
    void receivingPercent(int percent);//接收过程中发送接收文件的百分比
  34.  
    };
  35.  
     
  36.  
    #endif // RECVFILE_H
学新通

3.客户端代码实现

 mainwindow.cpp

  1.  
    #include "mainwindow.h"
  2.  
    #include "ui_mainwindow.h"
  3.  
    #include<sendfile.h>
  4.  
    #include<QThread>
  5.  
    #include<QMessageBox>
  6.  
    //多线程TCP通信的客户端
  7.  
    MainWindow::MainWindow(QWidget *parent)
  8.  
    : QMainWindow(parent)
  9.  
    , ui(new Ui::MainWindow)
  10.  
    {
  11.  
    ui->setupUi(this);
  12.  
    qDebug()<<"主线程地址为"<<QThread::currentThread();
  13.  
    ui->disconnectBt->setDisabled(true);//初始不能断开连接
  14.  
    setWindowTitle("客户端");
  15.  
    //ip,端口号初始化
  16.  
    ui->PortEdit->setText("30201");
  17.  
    getIPInfo();//IP、端口号填充
  18.  
    //进度条初始化
  19.  
    ui->progressBar->setRange(0,100);
  20.  
    ui->progressBar->setValue(0);
  21.  
    connect_FileThread();//子线程初始化和槽函数连接
  22.  
    tab1 = new QTabWidget(this);
  23.  
    QWidget *tcp_tab = new QWidget;
  24.  
    QWidget *serial_tab = new QWidget;
  25.  
    tab1->addTab(tcp_tab,"tcp");
  26.  
    tab1->addTab(serial_tab,"ser");
  27.  
    //状态栏初始化
  28.  
    m_status = new QLabel;
  29.  
    m_status->setPixmap(QPixmap(":/red.jpeg").scaled(20,20));
  30.  
    ui->statusbar->addWidget(new QLabel("连接状态"));
  31.  
    ui->statusbar->addWidget(m_status);
  32.  
    }
  33.  
     
  34.  
    MainWindow::~MainWindow()
  35.  
    {
  36.  
    delete ui;
  37.  
    }
  38.  
     
  39.  
     
  40.  
    //发送文件线程连接
  41.  
    void MainWindow::connect_FileThread()
  42.  
    {
  43.  
    /*多线程相关对象的实例化*/
  44.  
    //创建线程对象
  45.  
    QThread *m_thread = new QThread;
  46.  
    //创建任务对象
  47.  
    SendFile* worker = new SendFile;
  48.  
    //任务对象移动到子线程中
  49.  
    worker->moveToThread(m_thread);//任务对象会在子线程中执行
  50.  
     
  51.  
    //主窗口发送开启连接的信号,接收信号的对象是worker,子线程中SendFile类的connectServer进行工作
  52.  
    connect(this,&MainWindow::startConnect,worker,&SendFile::connectServer);
  53.  
     
  54.  
    //主窗口发送关闭连接信号
  55.  
    connect(this,&MainWindow::closeConnect,worker,&SendFile::closeConnect);
  56.  
     
  57.  
    //子线程中完成连接发送信号,主线程接收到以后弹出messagebox
  58.  
    connect(worker,&SendFile::connected_ok,this,[=]()
  59.  
    {
  60.  
    //连接以后的状态转换
  61.  
    ui->statusLabel->setText("已经连接");
  62.  
    //QMessageBox::information(this,"连接服务器","已成功连接");
  63.  
    m_status->setPixmap(QPixmap(":/green.jpeg").scaled(20,20));
  64.  
    ui->disconnectBt->setEnabled(true);
  65.  
    ui->connectBt->setDisabled(true);
  66.  
     
  67.  
    });
  68.  
    //子线程中检测到断开连接则释放资源(销毁各种对象)
  69.  
    connect(worker,&SendFile::tcp_over,this,[=]()
  70.  
    {
  71.  
    //ui状态转换
  72.  
    m_status->setPixmap(QPixmap(":/red.jpeg").scaled(20,20));
  73.  
    ui->disconnectBt->setEnabled(false);
  74.  
    ui->connectBt->setDisabled(false);
  75.  
    //资源释放
  76.  
    //m_thread->quit();
  77.  
    //m_thread->wait();
  78.  
    //worker->deleteLater();
  79.  
    //m_thread->deleteLater();
  80.  
     
  81.  
    });
  82.  
    //在子线程中发送文本
  83.  
    connect(this,&MainWindow::sendText,worker,&SendFile::sendText);
  84.  
     
  85.  
    //子线程接收到文本,在主线程中更新窗口
  86.  
    connect(worker,&SendFile::recv_txt,this,[=](QByteArray buf)
  87.  
    {
  88.  
    ui->recvEdit->append("服务器发送:" buf);
  89.  
    });
  90.  
     
  91.  
    //子线程中发送文件
  92.  
    connect(this,&MainWindow::sendFile_Path,worker,&SendFile::sendFile);
  93.  
    //更新发送速度
  94.  
    //connect(worker,&SendFile::send_Speed,this,[=](double speed)
  95.  
    //{
  96.  
    // ui->speedLabel->setText(tr("发送速度%1 MB/S").arg(speed,0,'f',2));
  97.  
    //});
  98.  
     
  99.  
    //更新进度条
  100.  
    connect(worker,&SendFile::curPercent,ui->progressBar,&QProgressBar::setValue);
  101.  
     
  102.  
    //开启子线程
  103.  
    m_thread->start();
  104.  
    }
  105.  
     
  106.  
     
  107.  
    void MainWindow::on_sendTextBt_clicked()
  108.  
    {
  109.  
    QString msg = ui->SendEdit->toPlainText();//从UI中获取发送的信息
  110.  
    emit sendText(msg);//给sendfile类发送信号
  111.  
    }
  112.  
     
  113.  
     
  114.  
    void MainWindow::getIPInfo()
  115.  
    {
  116.  
    QString localHostName = QHostInfo::localHostName();
  117.  
    QHostInfo hostinfo = QHostInfo::fromName(localHostName);
  118.  
    QList<QHostAddress> listAddress = hostinfo.addresses();
  119.  
    if(!listAddress.isEmpty() )
  120.  
    {
  121.  
    ui->ipEdit->setText(listAddress.at(0).toString());
  122.  
    }
  123.  
     
  124.  
     
  125.  
    }
  126.  
     
  127.  
     
  128.  
    void MainWindow::on_connectBt_clicked()
  129.  
    {
  130.  
    QString ip = ui->ipEdit->text();
  131.  
    unsigned short port = ui->PortEdit->text().toUInt();
  132.  
    emit startConnect(port,ip);
  133.  
    }
  134.  
     
  135.  
    void MainWindow::on_disconnectBt_clicked()
  136.  
    {
  137.  
     
  138.  
    ui->disconnectBt->setEnabled(false);//断开连接按钮不可用
  139.  
    ui->connectBt->setDisabled(false);//连接按钮可用
  140.  
    emit closeConnect();//发送断开连接信号
  141.  
     
  142.  
    }
  143.  
     
  144.  
    void MainWindow::on_selectFileBt_clicked()
  145.  
    {
  146.  
    QString path = QFileDialog::getOpenFileName();
  147.  
    ui->filePathEdit->setText(path);
  148.  
    //获取文件信息
  149.  
    QFileInfo info(path);
  150.  
    fileSize = info.size(); //文件大小
  151.  
    fileName = info.fileName();//文件名
  152.  
     
  153.  
    qDebug()<<"fileSize:"<<fileSize<<endl;
  154.  
    ui->statusLabel->setText(tr("打开 %1 文件成功!").arg(fileName));
  155.  
     
  156.  
    if(image.load(path))//当图像文件导入以后
  157.  
    {
  158.  
    //显示图像
  159.  
    ui->picShow_Label->setPixmap(QPixmap::fromImage(image).scaled(ui->picShow_Label->size()));
  160.  
    }
  161.  
     
  162.  
    }
  163.  
     
  164.  
    void MainWindow::on_sendFileBt_clicked()
  165.  
    {
  166.  
    emit sendFile_Path(ui->filePathEdit->text());
  167.  
    }
学新通

mainwidow.h

  1.  
    #ifndef MAINWINDOW_H
  2.  
    #define MAINWINDOW_H
  3.  
     
  4.  
    #include <QMainWindow>
  5.  
     
  6.  
    #include<QHostInfo>
  7.  
    #include <QTcpSocket>
  8.  
    #include<QLabel>
  9.  
    #include<QFile>
  10.  
    #include<QFileDialog>
  11.  
    #include<QFileInfo>
  12.  
    #include<QImage>
  13.  
    #include<QTabWidget>
  14.  
    QT_BEGIN_NAMESPACE
  15.  
    namespace Ui { class MainWindow; }
  16.  
    QT_END_NAMESPACE
  17.  
     
  18.  
    class MainWindow : public QMainWindow
  19.  
    {
  20.  
    Q_OBJECT
  21.  
     
  22.  
    public:
  23.  
    MainWindow(QWidget *parent = nullptr);
  24.  
    ~MainWindow();
  25.  
     
  26.  
    private slots:
  27.  
     
  28.  
    void on_sendTextBt_clicked();
  29.  
     
  30.  
    void on_connectBt_clicked();
  31.  
     
  32.  
    void on_disconnectBt_clicked();
  33.  
     
  34.  
    void on_selectFileBt_clicked();
  35.  
     
  36.  
    void on_sendFileBt_clicked();
  37.  
     
  38.  
    private:
  39.  
    Ui::MainWindow *ui;
  40.  
    QTabWidget *tab1;
  41.  
    QImage image;//图像文件
  42.  
    QString fileName;//图片名
  43.  
    qint64 fileSize;//文件大小
  44.  
    QTcpSocket* m_sock;
  45.  
    void getIPInfo();
  46.  
    QLabel* m_status;
  47.  
    void connect_FileThread();
  48.  
    signals:
  49.  
    void startConnect(unsigned short port,QString ip);
  50.  
    void closeConnect();//断开连接信号
  51.  
    void sendText(QString data);
  52.  
    void sendFile_Path(QString path);
  53.  
    };
  54.  
    #endif // MAINWINDOW_H
学新通

sendfile.cpp

  1.  
    #include "sendfile.h"
  2.  
    #include<QHostAddress>
  3.  
    #include<QFileInfo>
  4.  
    #include<QElapsedTimer>
  5.  
    SendFile::SendFile(QObject *parent) : QObject(parent)
  6.  
    {
  7.  
     
  8.  
    tcpSocket = new QTcpSocket;
  9.  
    //当有文本数据接收到时发射recv_txt信号给主窗口
  10.  
    connect(tcpSocket,&QTcpSocket::readyRead,this,[=]()
  11.  
    {
  12.  
    QByteArray buf = tcpSocket->readAll();
  13.  
    emit recv_txt(buf);
  14.  
    });
  15.  
    //断开连接发送tcp_over
  16.  
    connect(tcpSocket,&QTcpSocket::disconnected,this,[=]()
  17.  
    {
  18.  
    tcpSocket->close();
  19.  
    //tcpSocket->deleteLater();
  20.  
    emit tcp_over();
  21.  
    });
  22.  
     
  23.  
    }
  24.  
     
  25.  
    void SendFile::connectServer(unsigned short port, QString ip)
  26.  
    {
  27.  
    qDebug()<<"子线程地址为"<<QThread::currentThread();
  28.  
    //tcpSocket = new QTcpSocket;
  29.  
    tcpSocket->connectToHost(QHostAddress(ip),port);//连接操作
  30.  
    //已经连接发送connnected_ok
  31.  
    connect(tcpSocket,&QTcpSocket::connected,this,&SendFile::connected_ok);
  32.  
     
  33.  
    }
  34.  
     
  35.  
    void SendFile::closeConnect()
  36.  
    {
  37.  
    tcpSocket->disconnectFromHost();
  38.  
    tcpSocket->close();
  39.  
    }
  40.  
     
  41.  
    void SendFile::sendFile(QString path)
  42.  
    {
  43.  
    QElapsedTimer timer;//定时器记录程序执行使用时间
  44.  
    QFile file(path);
  45.  
    QFileInfo info(path);
  46.  
    qint64 fileSize = info.size();
  47.  
    QString fileName = info.fileName();
  48.  
    file.open(QFile::ReadOnly);
  49.  
    timer.start();
  50.  
    while (!file.atEnd())
  51.  
    {
  52.  
    if(num == 0)
  53.  
    {
  54.  
    QString head = QString("head#%1#%2").arg(fileName).arg(fileSize);
  55.  
    tcpSocket->write(head.toUtf8().data());
  56.  
    tcpSocket->waitForBytesWritten(); //等待数据发送完毕
  57.  
    }
  58.  
    QByteArray line = file.readLine();
  59.  
    num =line.size();
  60.  
    //qDebug()<<"已发送文件大小"<<num;
  61.  
    //sendSpeed = num / ( milsec * 1024 ) ;//发送速度
  62.  
    //qDebug()<<"发送速度"<<sendSpeed;
  63.  
    //emit send_Speed(sendSpeed);//向主线程发送速度
  64.  
    qint64 percent = (num * 100 /fileSize);
  65.  
    emit curPercent(percent);
  66.  
    tcpSocket->write(line);
  67.  
    }
  68.  
    //文件发送完成以后的善后工作
  69.  
    num = 0;
  70.  
    int milsec = timer.elapsed();
  71.  
     
  72.  
    qDebug()<<"发送消耗时间"<<milsec<<"毫秒";
  73.  
    file.close();
  74.  
    }
  75.  
     
  76.  
    void SendFile::sendText(QString data)
  77.  
    {
  78.  
    tcpSocket->write(data.toUtf8());
  79.  
    }
  80.  
     
  81.  
     
学新通

sendfile.h

  1.  
    #ifndef SENDFILE_H
  2.  
    #define SENDFILE_H
  3.  
     
  4.  
    #include <QObject>
  5.  
    #include<QTcpSocket>
  6.  
    #include<QFile>
  7.  
    #include<QFileDialog>
  8.  
    #include<QThread>
  9.  
    class SendFile : public QObject
  10.  
    {
  11.  
    Q_OBJECT
  12.  
    public:
  13.  
    explicit SendFile(QObject *parent = nullptr);
  14.  
    //连接服务器
  15.  
    void connectServer(unsigned short port,QString ip);
  16.  
    //与服务器断开连接
  17.  
    void closeConnect();
  18.  
    //发送文件
  19.  
    void sendFile(QString path);
  20.  
    //发送文本
  21.  
    void sendText(QString data);
  22.  
    private:
  23.  
    QTcpSocket* tcpSocket ;
  24.  
    qint64 num=0;
  25.  
    qint64 sendSpeed = 0;
  26.  
    signals:
  27.  
    void connected_ok();
  28.  
    void tcp_over();
  29.  
    void recv_txt(QByteArray buf);
  30.  
    void curPercent(int percent);
  31.  
    void send_Speed(qint64 speed);
  32.  
     
  33.  
    };
  34.  
     
  35.  
    #endif // SENDFILE_H
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhhkjbkh
系列文章
更多 icon
同类精品
更多 icon
继续加载