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

QT项目二支持大文件传输的文件传输程序

武飞扬头像
霄阳~
帮助1

目录

一、关键技术点

1、服务器多线程

2、收发数据

具体代码

1、服务器

main.cpp

myservices.cpp

myservices.h

thread.cpp

thread.h

客户端

main.cpp

widget.cpp

widget.h

mythread.cpp

mythread.h


一、关键技术点

1、服务器多线程

要实现服务器一对多需要自定义一个继承于qtcpserver的类,并重写该类中的inconingconnection函数。
在该函数中再new一个新线程,在线程中接收数据。当有客户端连接时,就会调用inconingconnection函数,实例化一个线程。

学新通

2、收发数据

1、connect(newsocet,SIGNAL(readyRead()),this,SLOT(parsing_data()));//有数据来就读取
服务器中readyRead(),一有数据就读取,但是经过多次实验发现:发送端发送数据与接收端接收端接收数据并不是一个一个地对应的,这应该是qt做过某种优化。有可能,发送了几次数据,而接收端只触发一次信号。再有,如果发送端速率远远大于接收的速率,程序直接就崩溃了。如果是只是发一些小的文件,这些完全不用考虑,收发各一次就可以了。
    本项目想收发个超级大的文件,就必须解决该问题。归根到底就是,tcp发送与接收不一致导致的粘包问题。
    
    思路:
        1、自定义一个结构体,对收发数据进行分类。先保证双方具有收发条件(发送方能打开文件并读取文件,接收方能创建文件并写入文件),再进行发送数据。
        2、由于qt中用readyRead(),本来就会导致收发速率不一致,那就只有牺牲效率保证效果(我自己的想法)。进行约定,发送方发一个包,等到接收放接收后发一个反馈包后再发下一个(我这里默认接收方发的反馈包发送方一定能接收到,其实这里应该弄一个定时器,到了一定时间还没有反馈包就应该退出程序了,否则一直阻塞在等待反馈)。
        3、收发双方,每次收到的数据都会根据结构体不同的标志位,拥有不同的处理方式。
        4、客户端发数据线程与主界面用信号与槽交流打印进度条。
       





学新通

效果演示:

学新通

具体代码

1、服务器

main.cpp

  1.  
    #include <QCoreApplication>
  2.  
    #include "myservices.h"
  3.  
  4.  
    int main(int argc, char *argv[])
  5.  
    {
  6.  
      QCoreApplication a(argc, argv);
  7.  
      myservices server;
  8.  
  9.  
      server.listen(QHostAddress::AnyIPv4,6150);
  10.  
  11.  
      return a.exec();
  12.  
    }

myservices.cpp

  1.  
    #include "myservices.h"
  2.  
  3.  
    myservices::myservices(QObject * parent )
  4.  
      : QTcpServer(parent)
  5.  
    {
  6.  
  7.  
    }

myservices.h

  1.  
    #ifndef MYSERVICES_H
  2.  
    #define MYSERVICES_H
  3.  
    #include<QTcpServer>
  4.  
    #include<QThread>
  5.  
    #include<QTcpSocket>
  6.  
    #include "thread.h"
  7.  
    #include<QVector>
  8.  
    #include<QAbstractSocket>
  9.  
    #include<QDebug>
  10.  
    #include<QHostAddress>
  11.  
    class myservices : public QTcpServer
  12.  
    {
  13.  
      Q_OBJECT
  14.  
    public:
  15.  
      myservices(QObject * parent =nullptr );
  16.  
  17.  
    private:
  18.  
      void incomingConnection(qintptr s)
  19.  
      {
  20.  
          th = new qthread(s);
  21.  
          th->start();
  22.  
      }
  23.  
    public slots:
  24.  
      //void stat_run();
  25.  
  26.  
    private:
  27.  
  28.  
      qthread * th;
  29.  
  30.  
    };
  31.  
  32.  
    #endif // MYSERVICES_H
学新通

thread.cpp

学新通

  1.  
    #include "thread.h"
  2.  
  3.  
    qthread::qthread(qintptr newsocket_qintptr)
  4.  
      :newsocket_qintptr(newsocket_qintptr)
  5.  
    {
  6.  
      newsocet =new QTcpSocket;
  7.  
      newsocet->setSocketDescriptor(newsocket_qintptr);//由描述符获得套接字
  8.  
  9.  
      connect(newsocet,SIGNAL(readyRead()),this,SLOT(parsing_data()));//有数据来就读取
  10.  
  11.  
      port= newsocet->peerPort();
  12.  
  13.  
    }
  14.  
    void qthread::run()
  15.  
    {
  16.  
  17.  
    }
  18.  
  19.  
    void qthread::parsing_data()//每次收到的信息需要分类处理
  20.  
    {
  21.  
  22.  
      struct stu buf;//接收信息的结构体
  23.  
      array1 = new QByteArray(newsocet->readAll());//接收信息的数组
  24.  
      //qDebug()<<"mm"<< mm;
  25.  
      memcpy(&buf,array1->data(),sizeof(struct stu));//转化到结构体
  26.  
      if(0 == buf.type)//本次数据不是文件
  27.  
      {
  28.  
          get_data(array1);
  29.  
      }else if(1 == buf.type)//本次数据为文件相关
  30.  
      {
  31.  
          if(1 == buf.a )
  32.  
              get_filename(array1);//获取文件名
  33.  
          if(1 == buf.b)//客户端文件打开成功
  34.  
          {
  35.  
              type2 =1;
  36.  
              read_num = buf.read_num;
  37.  
              tail_num = buf.tail_num;
  38.  
              // qDebug()<<"readnum:"<<read_num<<"tailnum:"<<tail_num;
  39.  
              struct stu buf;
  40.  
              buf.c =0;
  41.  
              buf.d = 2;
  42.  
              send_buf_to_client(buf);//服务器最后一次确认,客户端收到后直接发数据
  43.  
              return ;
  44.  
          }
  45.  
          else if(-1 == buf.b )
  46.  
          {//不能进行文件传输,两个都置零,意味整个过程需要重新来.并且删除已经创建的文件
  47.  
              type2 =0;
  48.  
              type1 =0;
  49.  
              file->remove();
  50.  
          }
  51.  
          if((1==type1)&& (1==type2))//准备工作已经做好,可以进入接收数据函数
  52.  
  53.  
          {
  54.  
              get_file();//开始接收数据
  55.  
          }
  56.  
      }
  57.  
    }
  58.  
  59.  
    void qthread::get_data(QByteArray *array)//获取其它信息
  60.  
    {
  61.  
      QByteArray array2;
  62.  
  63.  
      int i =0;
  64.  
      struct stu buf;//接收信息的结构体
  65.  
      int read_num =0;//数据包个数
  66.  
      int tail_num =0 ;//最后一次数句字数
  67.  
      memcpy(&buf,array->data(),sizeof(struct stu));//转化到结构体
  68.  
      read_num = buf.read_num ;//将数据包个数读出来
  69.  
      tail_num = buf.tail_num;//将最后一次字数读出来
  70.  
      while(read_num--)
  71.  
      {
  72.  
          memcpy(&buf, array->data() i*sizeof(struct stu),sizeof(struct stu));//将每个数据包从array中拿出来,发的结构体,拿的时候也拿结构体大小
  73.  
          array2.append(buf.ar);
  74.  
          i ;
  75.  
      }
  76.  
      qDebug()<<array2.toStdString().c_str();//打印到屏幕
  77.  
      array->resize(0);
  78.  
    }
  79.  
  80.  
  81.  
    void qthread::get_filename(QByteArray *array)//获取文件名
  82.  
    {
  83.  
      qDebug()<<"获取文件名";
  84.  
      struct stu buf;//接收信息的结构体
  85.  
      struct stu buf2;//回信息的结构体
  86.  
      memcpy(&buf,array->data(),sizeof(struct stu));//转化到结构体
  87.  
      qDebug()<< buf.filename;
  88.  
      //根据文件名检查文件名是否重名
  89.  
      QString str( buf.filename);
  90.  
      filename = str.section('/',-1);//去除路径,获得文件名,
  91.  
      QFileInfo fi(filename);
  92.  
      if( fi.isFile())//文件已经存在。
  93.  
      {
  94.  
          buf2.c = -1;
  95.  
          qDebug()<<"文件已经存在";
  96.  
      }else{//文件不存在,可以创建文件。
  97.  
          file = new QFile(filename);
  98.  
          if( file->open(QIODevice::WriteOnly))
  99.  
          {
  100.  
              buf2.c = 2;
  101.  
              type1=1;
  102.  
              qDebug()<<"创建文件成功";
  103.  
              qDebug()<<"type1"<<type1;
  104.  
          }//文件创建成功标志置位
  105.  
          else {buf2.c =-2;}//创建失败
  106.  
      }
  107.  
      buf2.d=0;
  108.  
      send_buf_to_client(buf2);//反馈创建文件情况
  109.  
      array->resize(0);
  110.  
    }
  111.  
  112.  
    void qthread::get_file()
  113.  
    {
  114.  
      struct stu buf;//接收数据结构体
  115.  
      memcpy(&buf, (array1->data()),sizeof(buf));//将每个数据包从array中拿出来,发的结构体,拿的时候也拿结构体大小
  116.  
      ii ;//收取数据包计数
  117.  
      struct stu buff;//反馈数据结构体
  118.  
      buff.d =1;//反馈数据标志位
  119.  
      buff.c = 0;//反馈数据标志位
  120.  
  121.  
      if(ii == (read_num))//最后一个包
  122.  
      {
  123.  
          file->write(buf.ar,tail_num);
  124.  
          type1 =0;
  125.  
          type2 = 0;
  126.  
          ii=0;
  127.  
          file->close();//传输完毕,所有标志位复位。等待下一次传输
  128.  
          qDebug()<< filename<<"传输完毕";
  129.  
          return;
  130.  
      }else{
  131.  
          qDebug()<< buf.ar;
  132.  
          file->write(buf.ar,sizeof(buf.ar));
  133.  
      }
  134.  
      if(read_num !=1)//文件太小只需要传输一次,不需要再反馈
  135.  
      {
  136.  
          usleep(1000);
  137.  
          send_buf_to_client(buff);//反馈创建文件情况
  138.  
      }
  139.  
    }
  140.  
    void qthread::send_buf_to_client(struct stu buf)//给客户端回消息
  141.  
    {
  142.  
      qDebug()<<"port: " <<port<<"反馈信息";
  143.  
      QByteArray array1;
  144.  
      array1.resize(sizeof(struct stu));
  145.  
      memcpy(array1.data(),&buf,sizeof(struct stu));
  146.  
      qDebug()<<"fanhui: "<< newsocet->write(array1) << "d" << buf.d;
  147.  
      newsocet->waitForBytesWritten();
  148.  
    }
  149.  
学新通

thread.h

  1.  
    #ifndef THREAD_H
  2.  
    #define THREAD_H
  3.  
    #define MAX (1024*13)
  4.  
    #include<QThread>
  5.  
    #include<QTcpSocket>
  6.  
    #include<iostream>
  7.  
    #include<QAbstractSocket>
  8.  
    #include<QDebug>
  9.  
    #include<QHostAddress>
  10.  
    #include<QInternal>
  11.  
    #include<QFile>
  12.  
    #include<QByteArray>
  13.  
    #include<QFile>
  14.  
    #include<QFileInfo>
  15.  
    struct stu{
  16.  
      char filename[128];
  17.  
      char ar[MAX];
  18.  
      int type;
  19.  
      int read_num;
  20.  
      int a;//告诉服务器创建文件
  21.  
      int b;//告诉服务器文件打开情况
  22.  
      int c;//服务器反馈信息
  23.  
      int d;
  24.  
      int tail_num;
  25.  
    };
  26.  
  27.  
  28.  
    class qthread : public QThread
  29.  
    {
  30.  
      Q_OBJECT
  31.  
    public:
  32.  
      qthread(qintptr newsocket_qintptr);
  33.  
      ~qthread()
  34.  
      {
  35.  
          newsocet->close();
  36.  
          delete newsocet;
  37.  
      }
  38.  
      void run();
  39.  
      void send_buf_to_client(struct stu);
  40.  
    public slots:
  41.  
      void get_file();//收文件
  42.  
      void get_data(QByteArray*);//收数据
  43.  
      void parsing_data();//解析数据,判断
  44.  
      void get_filename(QByteArray*);//收取文件名
  45.  
  46.  
    signals:
  47.  
  48.  
    private:
  49.  
      qintptr newsocket_qintptr;//套接字描述符
  50.  
      QTcpSocket *newsocet;//连接套接字
  51.  
      struct stu stu1;
  52.  
      int num =0;
  53.  
      QHostAddress ip;
  54.  
      QFile *file;
  55.  
      int type1 =0;//文件创建成功标志(0失败)
  56.  
      int type2 = 0;//客户端文件打开成功标志(0失败,)
  57.  
      int read_num;
  58.  
      int tail_num;
  59.  
      int ii=0;
  60.  
      QByteArray *array1;
  61.  
      int mm=0;
  62.  
      int d=0;
  63.  
      QString filename;
  64.  
  65.  
      int port;
  66.  
    };
  67.  
  68.  
    #endif // THREAD_H
  69.  
学新通

客户端

main.cpp

  1.  
    #include "widget.h"
  2.  
    #include <QApplication>
  3.  
  4.  
    int main(int argc, char *argv[])
  5.  
    {
  6.  
      QApplication a(argc, argv);
  7.  
      Widget w;
  8.  
      w.show();
  9.  
  10.  
      return a.exec();
  11.  
    }
  12.  

widget.cpp

  1.  
    #include "widget.h"
  2.  
    Widget::Widget(QWidget *parent)
  3.  
      : QWidget(parent)
  4.  
    {
  5.  
      // pgd = new QProgressDialog;
  6.  
      box = new QMessageBox;
  7.  
      tcp = new QTcpSocket;
  8.  
      te1 = new QTextEdit;//提示框
  9.  
      te1->setMinimumSize(200,200);
  10.  
      le = new QLineEdit("192.168.174.1");
  11.  
      bt1 = new QPushButton("发送信息");
  12.  
      bt3 = new QPushButton("取消连接");
  13.  
      bt2 =new QPushButton("连接");
  14.  
      bt4 = new QPushButton("选择文件");
  15.  
      bt5= new QPushButton("发送文件");
  16.  
      te2 = new QTextEdit;//ip输入
  17.  
      //   te2->setMaximumSize(200,70);
  18.  
      QGridLayout *gri = new QGridLayout;
  19.  
      gri->addWidget(te1,0,0,1,3);//提示框
  20.  
      gri->addWidget(le,1,0,1,2);//行编辑框
  21.  
      gri->addWidget(bt2,1,2,1,1);//连接按钮
  22.  
      gri->addWidget(te2,2,0,1,2);//输入框
  23.  
      gri->addWidget(bt4,2,2,1,1);//选择文件按钮
  24.  
      gri->addWidget(bt1,3,0,1,1);//发送按钮
  25.  
      gri->addWidget(bt5,3,1,1,1);//发送文件按钮
  26.  
      gri->addWidget(bt3,3,2,1,1);//取消连接按钮
  27.  
      setLayout(gri);
  28.  
      bt1->setDisabled(true);
  29.  
      bt5->setDisabled(true);
  30.  
  31.  
      th = new mythread(te1,le,te2);
  32.  
      connect(bt2,SIGNAL(clicked(bool)),th,SLOT(connect_server()));//连接服务器
  33.  
      connect(th,&mythread::connect_sucess,[&](){//线程返回连接成功,使能按钮
  34.  
          bt5->setDisabled(false);
  35.  
          bt1->setDisabled(false);
  36.  
      });
  37.  
      connect(bt3,SIGNAL(clicked(bool)),th,SLOT(discinnect()));//断开连接
  38.  
      connect(th,&mythread::disconnect_success,[&](){//线程返回断开连接成功,使能按钮
  39.  
          bt5->setDisabled(true);//失能按钮
  40.  
          bt1->setDisabled(true);//失能按钮
  41.  
      });
  42.  
      connect(bt4,SIGNAL(clicked(bool)),th,SLOT(choose_filename()));//选择文件
  43.  
      connect(bt1,SIGNAL(clicked(bool)),th,SLOT(send_data()));//发送信息
  44.  
      connect(bt5,SIGNAL(clicked(bool)),th,SLOT(send_filename()));//发送文件
  45.  
      connect(th,SIGNAL(remind_send_file()),this,SLOT(start_send_file()));//收到线程信号,可以让线程工作了
  46.  
      pgd = new QProgressBar;
  47.  
      pgd->setRange(0,100);
  48.  
      pgd->setMinimumSize(500,50);
  49.  
      pgd->setMaximumSize(500,50);
  50.  
      //pgd->setParent(this);
  51.  
      pgd->hide();
  52.  
      connect(th,SIGNAL(send_progress(int)),pgd,SLOT(setValue(int)));//进度条实时赋值
  53.  
  54.  
    }
  55.  
  56.  
    Widget::~Widget()
  57.  
    {
  58.  
  59.  
    }
  60.  
    void Widget::start_send_file()
  61.  
    {
  62.  
      th->start();
  63.  
      pgd->show();
  64.  
    }
学新通

widget.h

  1.  
    #ifndef WIDGET_H
  2.  
    #define WIDGET_H
  3.  
  4.  
    #include <QWidget>
  5.  
    #include<QDebug>
  6.  
    #include<QLineEdit>
  7.  
    #include<QTextEdit>
  8.  
    #include<QPushButton>
  9.  
    #include<QVBoxLayout>
  10.  
    #include<QHBoxLayout>
  11.  
    #include<QTcpSocket>
  12.  
    #include<QHostAddress>
  13.  
    #include<QGridLayout>
  14.  
    #include<QByteArray>
  15.  
    #include<QFileDialog>
  16.  
    #include<QByteArray>
  17.  
    #include<QMessageBox>
  18.  
    #include<QProgressDialog>
  19.  
    #include<QThread>
  20.  
    #include<QProgressBar>
  21.  
    #include "mythread.h"
  22.  
  23.  
  24.  
    class Widget : public QWidget
  25.  
    {
  26.  
      Q_OBJECT
  27.  
  28.  
    public:
  29.  
      Widget(QWidget *parent = 0);
  30.  
      ~Widget();
  31.  
    public slots:
  32.  
          void start_send_file();
  33.  
  34.  
    //       void stop_send_file();
  35.  
  36.  
    signals:
  37.  
  38.  
    private:
  39.  
      QTextEdit *te1;
  40.  
      QTextEdit *te2;
  41.  
      QLineEdit *le;
  42.  
      QPushButton *bt1;
  43.  
      QPushButton *bt2;
  44.  
      QPushButton *bt3;
  45.  
      QPushButton *bt4;
  46.  
      QPushButton *bt5;
  47.  
      QTcpSocket *tcp;
  48.  
      QMessageBox *box;
  49.  
      QStringList *filepaths;
  50.  
      QFile *file;
  51.  
      // int b=0;//服务器确认项,创建新文件成功(0失败)
  52.  
        QProgressBar *pgd;
  53.  
  54.  
      int read_num;//传输次数
  55.  
      int tail_num;//最后一次字节数
  56.  
      int d=0;
  57.  
      mythread *th;
  58.  
    };
  59.  
    #endif // WIDGET_H
  60.  
  61.  
     
  62.  
     
学新通

mythread.cpp

学新通

  1.  
    #include "mythread.h"
  2.  
  3.  
    mythread::mythread(QTextEdit *te1, QLineEdit *le,QTextEdit *te2)
  4.  
        :te1(te1),le(le),te2(te2)
  5.  
    {
  6.  
        tcp = new QTcpSocket;
  7.  
        connect(tcp,SIGNAL(readyRead()),this,SLOT(recv_data()));//接收信息
  8.  
        box = new QMessageBox;
  9.  
    }
  10.  
  11.  
    void mythread::run()
  12.  
    {
  13.  
        int i = 0;
  14.  
        struct stu buf;
  15.  
        buf.type =1;
  16.  
        buf.a=0;
  17.  
        buf.b = 0;//三个标志置位,代表本次数据为文件内容,服务器无需判断直接存储。
  18.  
        QByteArray array;
  19.  
        array.resize(sizeof(struct stu));
  20.  
        int read_num1  = read_num;//传输次数
  21.  
        while(1)//文件内容打包好发出去
  22.  
        {
  23.  
            if(d!=0)
  24.  
            {
  25.  
                i ;
  26.  
                qDebug()<<"read"<<read_num<<"tail_num"<<tail_num;
  27.  
                file->read(buf.ar,sizeof(buf.ar));
  28.  
                qDebug()<<buf.ar;
  29.  
                memcpy(array.data(),&buf,sizeof(struct stu));
  30.  
                read_num--;
  31.  
                tcp->write(array);
  32.  
                usleep(3000);
  33.  
                tcp->waitForBytesWritten(30000);
  34.  
                d =0;
  35.  
                emit send_progress((i%read_num1)>0?(i*100/read_num1 1):(i*100/read_num1));//发送进度
  36.  
            }
  37.  
            if(!read_num)//传输完毕,退出循环
  38.  
            {
  39.  
                file->close();
  40.  
                break;
  41.  
            }
  42.  
        }
  43.  
        qDebug()<<"文件传输完毕";
  44.  
    }
  45.  
  46.  
    void mythread::connect_server()//连接服务器
  47.  
    {
  48.  
        QString str = le->text();
  49.  
        tcp->connectToHost(str,6150);
  50.  
        if(tcp->waitForConnected(1000)){
  51.  
            te1->append("连接成功");
  52.  
            emit connect_sucess();//告诉界面连接成功
  53.  
        }else{
  54.  
            te1->append("连接失败");
  55.  
            emit connect_failed();
  56.  
        }
  57.  
    }
  58.  
    void mythread::discinnect()//断开连接
  59.  
    {
  60.  
        tcp->close();
  61.  
        te1->append("连接断开");
  62.  
        emit disconnect_success();
  63.  
    }
  64.  
  65.  
    void mythread::send_data()//发送较长消息
  66.  
    {
  67.  
        int i =0;
  68.  
        int num =0;
  69.  
        struct stu buf;
  70.  
        buf.type =0;
  71.  
        QByteArray array;//发送数据载体
  72.  
        QByteArray array1 =te2->toPlainText().toStdString().c_str() ;//把数据从文本框取出来
  73.  
        QByteArray array2 ;//中转载体
  74.  
  75.  
        array.resize(sizeof(struct stu));//重新设置数组大小
  76.  
        num = (array1.length())/(sizeof(buf.ar ));//本次发送整次数
  77.  
        buf.tail_num = (array1.length())%(sizeof( buf.ar)) ;//最后一次发送的字节数
  78.  
        if(buf.tail_num != 0){  num = 1;}//本次发送最终次数
  79.  
        buf.read_num = num;
  80.  
        qDebug()<< "num"<<buf.read_num;
  81.  
        while(num--)
  82.  
        {
  83.  
            if(num ==0 && buf.tail_num!= 0)//最后一次数据包字数
  84.  
            {
  85.  
                array2 = array1.mid(array1.length()-buf.tail_num,buf.tail_num);
  86.  
            }else{
  87.  
                array2 = array1.mid(i*MAX,MAX);
  88.  
            }
  89.  
            strncpy( buf.ar,array2.data(),sizeof(buf.ar));//数据存入结构体
  90.  
            memcpy(array.data(),&buf,sizeof(struct stu));//把结构体存入数组
  91.  
            qDebug()<<  tcp->write(array);//把数组发出去
  92.  
            qDebug()<<buf.ar;
  93.  
            i ;
  94.  
        }
  95.  
        te1->append("my: " te2->toPlainText());
  96.  
        te2->clear();
  97.  
        qDebug()<<"sucess";
  98.  
        return;
  99.  
    }
  100.  
  101.  
    void mythread::recv_data()//接收信息
  102.  
    {
  103.  
        QByteArray array;
  104.  
        struct stu buf;
  105.  
        array.resize(sizeof(struct stu));
  106.  
        array =  tcp->readAll();
  107.  
        memcpy(&buf,array.data(),sizeof(struct stu));
  108.  
        if(-1 == buf.c)//文件已经存在
  109.  
        {
  110.  
            qDebug()<<"文件已经存在";
  111.  
            box->setText("文件名重名,重新改个名字试试吧。");
  112.  
            box->setInformativeText("注意:需要更改源文件名字,而不是直接在本软件中更改。");
  113.  
            box->setStandardButtons( QMessageBox::Discard | QMessageBox::Cancel);
  114.  
            box->setDefaultButton(QMessageBox::Save);
  115.  
            box->exec();
  116.  
            return;
  117.  
        }
  118.  
        if(-2 == buf.c)//文件打开失败
  119.  
        {
  120.  
            return;
  121.  
        }
  122.  
        if(buf.d ==1)//服务器每次接收确认
  123.  
        {
  124.  
            d =buf.d;
  125.  
        }else if(buf.d  ==2)//服务器最后一次确认。
  126.  
        {
  127.  
            d =buf.d;
  128.  
            emit remind_send_file();//提醒界面可以启动线程run函数了
  129.  
        }
  130.  
        if(2 == buf.c)//服务器创建并文件打开成功
  131.  
            open_file();//打开本地文件
  132.  
    }
  133.  
  134.  
  135.  
  136.  
    void mythread::choose_filename()//选择文件
  137.  
    {
  138.  
        QStringList list = QFileDialog::getOpenFileNames();
  139.  
  140.  
        filepaths = new QStringList(list);
  141.  
        te2->clear();
  142.  
        for(int i=0; i<filepaths->length(); i )
  143.  
        {
  144.  
            te2->append((*filepaths)[i]);
  145.  
        }
  146.  
    }
  147.  
  148.  
    void mythread::send_filename()  //打包文件名,并发送
  149.  
    {
  150.  
        struct stu buf_filename;
  151.  
        QByteArray array;
  152.  
        array.resize(sizeof(struct stu));//给array分配空间
  153.  
        QByteArray array1= QString((*filepaths)[0]).toStdString().c_str();//将文件名转存在数组中
  154.  
        strncpy(buf_filename.filename,array1.data(),sizeof(buf_filename.filename));//数组内容打包到结构体中
  155.  
        buf_filename.type =1;//提示服务器,本次数据属于文件子路
  156.  
        buf_filename.a =1;//高速服务器本条消息为文件名
  157.  
        buf_filename.read_num =1;//本次仅传输一次
  158.  
        memcpy(array.data(),&buf_filename,sizeof(buf_filename));//把结构体存入数组
  159.  
        qDebug()<<  tcp->write(array);//把数组发出去
  160.  
        //    QString str( buf_filename.filename);
  161.  
        //    QString  filename = str.section('/',-1);//去除路径,获得文件名,
  162.  
        file = new QFile(buf_filename.filename);
  163.  
        qDebug()<<buf_filename.filename <<"文件名";
  164.  
    }
  165.  
  166.  
  167.  
  168.  
    void mythread::open_file()//打开本地文件
  169.  
    {
  170.  
        struct stu buf;
  171.  
        QByteArray array;
  172.  
        buf.type=1;
  173.  
        buf.a=0;
  174.  
        array.resize(sizeof(struct stu));
  175.  
        if(file->open(QIODevice::ReadOnly))
  176.  
        {
  177.  
            buf.b=1;
  178.  
            if(!file->size())
  179.  
            {
  180.  
                buf.b=-1;
  181.  
                box->setText("源文件不能为空。");
  182.  
                box->setInformativeText("请查看源文件是否为空。");
  183.  
                box->setStandardButtons( QMessageBox::Discard | QMessageBox::Cancel);
  184.  
                box->setDefaultButton(QMessageBox::Save);
  185.  
                box->exec();
  186.  
                file->close();
  187.  
                memcpy(array.data(),&buf,sizeof(struct stu));
  188.  
                tcp->write(array);//告诉服务器,文件为空。
  189.  
                return ;
  190.  
            }
  191.  
  192.  
            buf.tail_num = (file->size()%sizeof(buf.ar));
  193.  
            buf.read_num = file->size()/sizeof(buf.ar) ((buf.tail_num)>0?1:0);
  194.  
            read_num = buf.read_num;//计算出传输次数
  195.  
            tail_num =  buf.tail_num;//最后一次字节数
  196.  
            qDebug()<<"readnum:"<<read_num<<"tailnum:"<<tail_num;
  197.  
            qDebug()<<"filenum"<<file->size();
  198.  
  199.  
            memcpy(array.data(),&buf,sizeof(struct stu));
  200.  
            tcp->write(array);//告诉服务器,这边已经准备好了
  201.  
            tcp->waitForBytesWritten(3000);
  202.  
        }else{
  203.  
            qDebug()<<"sdsdesdwe";
  204.  
            buf.b=-1;
  205.  
            box->setText("文件打开失败");
  206.  
            box->setInformativeText("文件打开失败,请检查下文件。");
  207.  
            box->setStandardButtons( QMessageBox::Discard | QMessageBox::Cancel);
  208.  
            box->setDefaultButton(QMessageBox::Save);
  209.  
            box->exec();
  210.  
            memcpy(array.data(),&buf,sizeof(struct stu));
  211.  
            tcp->write(array);
  212.  
            return ;
  213.  
        }
  214.  
        return ;
  215.  
    }
  216.  
学新通


mythread.h

  1.  
    #ifndef MYTHREAD_H
  2.  
    #define MYTHREAD_H
  3.  
    #define MAX (1024*13)
  4.  
  5.  
    #include<QHostAddress>
  6.  
    #include<QByteArray>
  7.  
    #include<QFileDialog>
  8.  
    #include<QMessageBox>
  9.  
    #include<QProgressDialog>
  10.  
    #include<QThread>
  11.  
    #include<QTcpSocket>
  12.  
    #include<QDebug>
  13.  
    #include<QTextEdit>
  14.  
    #include<QLineEdit>
  15.  
    #include<QObject>
  16.  
    #include<QFile>
  17.  
    #include<QFileDialog>
  18.  
    #include<QMessageBox>
  19.  
    #include<QProgressBar>
  20.  
    struct stu{
  21.  
      char filename[128];//文件名
  22.  
      char ar[MAX];//数据体
  23.  
      int type;//传输的是否是文件
  24.  
      int read_num;//传输次数
  25.  
      int a;//告诉服务器创建文件
  26.  
      int b;//告诉服务器文件打开情况
  27.  
      int c;//服务器反馈信息
  28.  
      int d=1;
  29.  
      int tail_num;//最后一次字节数
  30.  
    };
  31.  
  32.  
    class mythread : public QThread
  33.  
    {
  34.  
      Q_OBJECT
  35.  
    public:
  36.  
      mythread(QTextEdit *, QLineEdit *,QTextEdit *);
  37.  
      void run();
  38.  
  39.  
      void open_file();//打开本地文件
  40.  
      void send_filedata();//发送文件
  41.  
    signals:
  42.  
      void connect_sucess();//发出信号,连接成功
  43.  
      void connect_failed();//发出信号连接失败
  44.  
      void disconnect_success();//发出信号已经断开连接
  45.  
      void remind_send_file();//提醒界面可以启动线程run函数发文件了
  46.  
      void send_progress(int);
  47.  
  48.  
    public slots:
  49.  
      void connect_server();//执行连接
  50.  
      void discinnect();//断开连接
  51.  
      void choose_filename();//选择文件
  52.  
      void send_data();//发送较长消息
  53.  
      void send_filename(); //打包文件名,并发送
  54.  
      void recv_data();//接收信息
  55.  
  56.  
  57.  
    private:
  58.  
      QTcpSocket *tcp;
  59.  
      QTextEdit *te1;
  60.  
      QLineEdit *le;
  61.  
      QTextEdit *te2;
  62.  
      QStringList *filepaths;
  63.  
      QFile *file;
  64.  
      int read_num;//传输次数
  65.  
      int tail_num;//最后一次字节数
  66.  
      int d=1;
  67.  
      QMessageBox *box;
  68.  
  69.  
    };
  70.  
  71.  
    #endif // MYTHREAD_H
  72.  
学新通

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

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