精华内容
下载资源
问答
  • qt实现的服务端,可以同时接收个客户端的连接,同时接收个客户端的文件传输任务。
  • qt多线程传输文件的静态编译版本,qt多线程传输文件的静态编译版本
  • 使用Qt编写的局域网多线程文件传输工具,设计网络,多线程,模型视图委托编程
  • 编写环境是VS2010和Qt4.8.5,工程分为客户端和服务器端,可以实现局域网的通信,涉及到TCP、UDP、多线程文件传输等知识
  • qt 多线程实现样例,实现文件的拷贝,亲测可用,重新编译即可
  • Qt编写项目作品27-多线程文件传输

    千次阅读 2020-05-10 15:16:52
    多线程收发文件,支持加密传输。 接收端支持监听端口接收文件和主动连接服务器接收文件两种方式。 按照 文件开始符+文件大小+文件内容+文件结束符 逐个分包接收。 可对接收的加密过的文件包进行解密输出。 如果采用...

    一、功能特点

    1. 多线程收发文件,支持加密传输。
    2. 接收端支持监听端口接收文件和主动连接服务器接收文件两种方式。
    3. 按照 文件开始符+文件大小+文件内容+文件结束符 逐个分包接收。
    4. 可对接收的加密过的文件包进行解密输出。
    5. 如果采用连接服务器方式接收文件可指定请求文件。
    6. 接收端请求文件的形式可以作为通用的程序升级方案。
    7. 进度条实时更新收发文件的进度。
    8. 发送端可设置每个包最大大小即切片分包数量。
    9. 发送端可对文件的每个包进行加密传输。
    10. 发送端支持对包进行合并发送。
    11. 可指定目录对客户端发来的请求文件进行搜索。
    12. 每个功能独立的一个类,接口清晰友好,使用方便。
    13. 支持任意Qt版本、任意系统、任意编译器。

    二、效果图

    在这里插入图片描述

    三、体验地址

    1. 体验地址:https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A 提取码:o05q 文件名:bin_tcpfile.zip
    2. 国内站点:https://gitee.com/feiyangqingyun
    3. 国际站点:https://github.com/feiyangqingyun
    4. 个人主页:https://blog.csdn.net/feiyangqingyun
    5. 知乎主页:https://www.zhihu.com/people/feiyangqingyun/
    展开全文
  • 然后又想弄个多线程文件传输 然后就遇到问题了 1. 首先传输小文件没问题,然后传送一般的不是很大的文件的时候就会出现客户端发送完毕,而服务器没有接收完的情况,这是什么原因? ![图片说明]...
  • 1. 效果 先看看效果图 这是传输文件完成的界面 ...这次是用多线程实现的文件传输系统,其中对客户端来说,子线程负责连接服务器,发送文件,主线程负责修改进度条,对服务端来说,也是用子线程来处理客户

    1. 效果

    先看看效果图

    • 这是传输文件完成的界面
      在这里插入图片描述
    • 客户端
      在这里插入图片描述
    • 服务端
      在这里插入图片描述

    2. 知识准备

    其实文件传输和聊天室十分相似,只不过一个传输的是文字,一个传输的是文件,而这方面的知识,我已经在前面的博客写过了,不了解的同学可以去看一下

    还有多线程相关的知识

    2.1 关于多线程

    这次是用多线程实现的文件传输系统,其中对客户端来说,子线程负责连接服务器,发送文件,主线程负责修改进度条,对服务端来说,也是用子线程来处理客户端的请求

    2.2 关于文件传输

    文件传输采用的是,对客户端,首先是发送出整个文件的大小,需要用到QFileInfo这个类,然后再发送文件

    对服务端,先接收文件的大小,然后判断,当接收的文件大小等于第一次接收的文件大小时,停止接收,断开连接

    3. 源代码

    我在代码里面都有非常详细的注释,所以就直接放上代码啦

    3.1 客户端

    头文件 mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    signals:
        void startConnect(unsigned short,QString);
        // 发送文件信号
        void sendFile(QString path);
    
    private slots:
        void on_connectServer_clicked();
    
        void on_selFile_clicked();
    
        void on_sendFile_clicked();
    
     private:
        Ui::MainWindow *ui;
    };
    #endif // MAINWINDOW_H
    
    

    源文件 mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QMessageBox>
    #include <QThread>
    #include "sendfile.h"
    #include <QFileDialog>
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        // 设置IP和端口
        ui->ip->setText("127.0.0.1");
        ui->port->setText("8989");
    
        // 设置进度条
        ui->progressBar->setRange(0,100);
        ui->progressBar->setValue(0);
    
        // 客户端在子线程中连接服务器
        // 创建线程对象
        QThread* t = new QThread;
    
        // 创建任务对象
        SendFile* worker = new SendFile;
    
        // 将worker移动到子线程t中
        worker->moveToThread(t);
    
    
        // 当发送sendFile信号,让worker的sendFile函数处理(子线程)
        connect(this,&MainWindow::sendFile,worker,&SendFile::sendFile);
    
    
        // 通过信号,让worker开始工作
        // 因为worker 已经移动到了子线程中,因此connectServer这个槽函数是在子线程中执行的
        connect(this,&MainWindow::startConnect,worker,&SendFile::connectServer);
    
        // 处理子线程发送的信号
        // 连接成功
        connect(worker,&SendFile::connectOK,this,[=](){
            QMessageBox::information(this,"连接服务器","已经成功的连接了服务器,恭喜!");
        });
    
        // 断开连接
        connect(worker,&SendFile::gameover,this,[=](){
            // 资源释放
            t->quit();
            t->wait();
            worker->deleteLater();
            t->deleteLater();
        });
    
        connect(worker,&SendFile::curPercent,ui->progressBar,&QProgressBar::setValue);
        // 启动线程
        t->start();
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    
    void MainWindow::on_connectServer_clicked()
    {
        QString ip = ui->ip->text();
        unsigned short port = ui->port->text().toUShort();
        emit startConnect(port,ip);
    
    }
    
    void MainWindow::on_selFile_clicked()
    {
        QString path = QFileDialog::getSaveFileName();
        // 判断路径是否为空
        if(path.isEmpty())
        {
            QMessageBox::warning(this,"打开文件","选择的文件路径不能为空");
            return;
        }
        ui->filePath->setText(path);
    }
    
    
    
    void MainWindow::on_sendFile_clicked()
    {
        // 发送文件信号
        emit sendFile(ui->filePath->text());
    }
    
    

    头文件 Send File.h

    #ifndef SENDFILE_H
    #define SENDFILE_H
    
    #include <QObject>
    #include <QTcpSocket>
    
    class SendFile : public QObject
    {
        Q_OBJECT
    public:
        explicit SendFile(QObject *parent = nullptr);
    
        // 连接服务器
        void connectServer(unsigned short port,QString ip);
    
        // 发送文件
        void sendFile(QString path);
    
    signals:
        // 通知主线程连接成功
        void connectOK();
        // 通知主线程连接成功
        void gameover();
        // 通知主线程发送文件进度百分比
        void curPercent(int num);
    
    
    private:
        QTcpSocket* m_tcp;
    };
    
    #endif // SENDFILE_H
    
    

    源文件SendFile.cpp

    #include "sendfile.h"
    
    #include <QFile>
    #include <QHostAddress>
    #include <QFileInfo>
    
    SendFile::SendFile(QObject* parent) : QObject(parent)
    {
    
    }
    
    void SendFile::connectServer(unsigned short port, QString ip)
    {
        m_tcp = new QTcpSocket;
        m_tcp->connectToHost(QHostAddress(ip),port);
    
        // 通知主线程连接成功
        connect(m_tcp,&QTcpSocket::connected,this,&SendFile::connectOK);
    
        // 通知主线程断开连接
        connect(m_tcp,&QTcpSocket::disconnected,this,[=](){
            // 断开连接,释放资源
            m_tcp->close();
            m_tcp->deleteLater();
            emit gameover();
        });
    }
    
    void SendFile::sendFile(QString path)
    {
        QFile file(path);
        // 获取文件信息
        QFileInfo info(path);
        int fileSize = info.size();
    
        file.open(QFile::ReadOnly);
    
        // 一行一行的读文件
        while(!file.atEnd()){
            static int num = 0;
            // 为了让服务器端知道什么时候停止接收,所以得发送文件的大小
            if(num ==0){
                m_tcp->write((char*)&fileSize,4);
            }
    
            QByteArray line = file.readLine();
            // 计算百分比,发给主线程
            num +=line.size();
            int percent =(num*100/fileSize);
            emit curPercent(percent);
            m_tcp->write(line);
    
    
        }
    
    }
    
    

    3.2 服务端

    头文件mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QTcpServer>
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private slots:
        void on_setListen_clicked();
    
    private:
        Ui::MainWindow *ui;
        QTcpServer* m_s;
    
    };
    #endif // MAINWINDOW_H
    
    

    源文件maindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    #include <QMessageBox>
    #include <QTcpSocket>
    #include "recvfile.h"
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        m_s = new QTcpServer(this);
    
    
        connect(m_s,&QTcpServer::newConnection,this,[=](){
            QTcpSocket* tcp = m_s->nextPendingConnection();
            // 创建子线程,tcp通过参数传递
            RecvFile* subThread = new RecvFile(tcp);
            subThread->start();
            connect(subThread,&RecvFile::over,this,[=](){
               subThread->exit();
               subThread->wait();
               subThread->deleteLater();
               QMessageBox::information(this,"文件接受","文件接收完毕!!!");
            });
        });
     
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    
    void MainWindow::on_setListen_clicked()
    {
        unsigned short port = ui->port->text().toUShort();
        m_s->listen(QHostAddress::Any,port);
    
    }
    
    

    头文件recvfile.h

    #ifndef RECVFILE_H
    #define RECVFILE_H
    
    #include <QThread>
    #include <QTcpSocket>
    class RecvFile : public QThread
    {
        Q_OBJECT
    public:
        explicit RecvFile(QTcpSocket* tcp,QObject *parent = nullptr);
    
    protected:
        void run() override;
    
    private:
        QTcpSocket* m_tcp;
    
    signals:
        void over();
    };
    
    #endif // RECVFILE_H
    
    

    源文件recvfile.cpp

    #include "recvfile.h"
    #include <QFile>
    RecvFile::RecvFile(QTcpSocket* tcp,QObject *parent) : QThread(parent)
    {
        m_tcp = tcp;
    }
    
    void RecvFile::run()
    {
        QFile* file = new QFile("recv.txt");
        file->open(QFile::WriteOnly);
    
        // 接收数据
        connect(m_tcp,&QTcpSocket::readyRead,this,[=](){
            static int count = 0;
            static int total = 0;
            if(count == 0){
                m_tcp->read((char*)&total,4);
            }
            // 读出剩余数据
            QByteArray all = m_tcp->readAll();
            count += all.size();
            file->write(all);
    
            if(count == total){
                m_tcp->close();
                m_tcp->deleteLater();
                file->close();
                file->deleteLater();
                emit over();
            }
        });
    
        // 进入事件循环
        exec();
    }
    
    

    3.4 文件目录

    在这里插入图片描述

    4. 结束语

    如果有些小伙伴需要工程文件等,可以联系我

    展开全文
  • github:https://github.com/xiaofengyun/FTP-FILE-transport ... 无线网络下基于FTP文件存储系统运行环境如下: 开发平台:Windows 10(客户端),Linux(服务端) 开发环境:Qt Creator,Ce...

    github:https://github.com/xiaofengyun/FTP-FILE-transport

                 https://github.com/xiaofengyun/FTP-FILE-transport.git

    无线网络下基于FTP文件存储系统运行环境如下:
    开发平台:Windows 10(客户端),Linux(服务端)
    开发环境:Qt Creator,Centos 7
    编译环境:G++,GDB,qmake
    运行环境:Qt 5.5.1,Centos 7

    多线程上传的逻辑:

    选择完一个文件后,通过偏移文件指针lseek()得到文件的size。接下来将大文件按照一定的方法拆分,首先,先比较文件的大小与切片大小,切片大小是一个定值。如果文件的大小小于切片的大小,那么不必进行多线程上传,单线程就可以了。当需要多线程上传的时候,首先计算出线程个数,通过用size/切片大小和size%切片大小的方式计算出需要的线程数。接下来便是传输文件,使用read()函数按字节去读取文件,每次读取一定的字节数到一个缓冲区。然后便是加标志位。犹豫线程是并发执行的,无法预测哪一个线程会首先完成传输,这会对文件的合并差生巨大的影响,所以必须加上标志位,判断数据片段是属于哪一个位置的。在缓冲区的前两个字节加上线程ID作为标志位,然后将读取的文件数据凭借到缓冲区后面,这样便组成了一个数据包,每个线程将这个数据包发送给服务端,然后自行关闭。

    客户端多线程上传程序:

    void MainWindow::thread_upload()/多线程上传
    {
    	qDebug() << "start thread upload...";
    	qint64 m_totalBytes;
    	QFile * m_localFile;
    
    	QString path = QFileDialog::getOpenFileName(this, "Open a file", "/", "files (*)");
    	QFileInfo info(path);//path就是打开文件的路径
    
    	m_localFile = new QFile(path);//类似一个文件指针
    	if (!m_localFile->open(QFile::ReadOnly))
    	{
    		qDebug() << "open file error!";
    		return;
    	}
    	//打开成功
    	qDebug() << "打开文件成功!";
    	m_totalBytes = m_localFile->size();//得到文件总大小
    	QString size = QString::number(m_totalBytes, 10);
    	qDebug() << "文件大小:" << m_localFile->size();
    	QString up = "upload";
    	up += " " + info.fileName() + " " + size;
    
    	char*  ch;
    	QByteArray ba = up.toLatin1(); // must
    	ch = ba.data();
    	sockfd->write(ch);///向服务端发送上传请求,等待回应
    	if (sockfd->waitForReadyRead(10))
    	{
    		QByteArray buff = sockfd->readAll();//接收服务端返回的消息
    		qDebug() << buff;
    		if (strncmp(buff, "ok", 2) != 0)
    		{
    			qDebug() << "server no message...";
    			return;
    		}
    		int n = 0;
    		int i = 0;
    		threadDown *thread[SIZE];
    		char sendbuff[1024] = { 0 };
    		size_int = size.toInt();
    		qDebug() << "size=" << size_int;
    		int num_thread = size_int / 1000;1000为分片大小,大小自己定义
    		if (size_int - num_thread * 1000>0)
    		{
    			num_thread++;///需要开启的线程数,也就是分片的个数
    		}
    		qDebug() << "thread=" << num_thread;
    
    		for (; i<num_thread; i++)
    		{
    			qDebug() << "i=" << i;
    
    			if (i <= 9)
    			{
    				sprintf(sendbuff, "%d", i);
    				sprintf(sendbuff + 1, "%s", NULL);
    			}
    			else
    			{
    				sprintf(sendbuff, "%d", i);
    			}
    			n = m_localFile->read(sendbuff + 2, 1000);每个数据包的前两个字节表示线程id,也就是标识符
    	
    			thread[i] = new threadDown(sendbuff, i); //新建线程对象,在线程中将数据发送就可以了
    			thread[i]->start();  //启动线程
    			bool b = connect(thread[i], SIGNAL(thread_to_main(char *, int)), this, SLOT(start_to_up(char *, int)));
    			qDebug() << "b=" << b;
    			thread[i]->wait();
    			memset(sendbuff, 0, sizeof(sendbuff));
    			qDebug() << "------------------------------------------------------------";
    		}	
    	}
    
    //多线程上传时,服务端接收处理程序
    while ((num = recv(c, buff, 1002, 0))>0)
    {
    	printf("num =%d\n", num);
    	printf("%s\n", buff);
    	char seq[2] = "";
    	seq[0] = buff[0];
    	seq[1] = buff[1];
    	//cout<<"seq="<<seq;
    	printf("seq=%s\n", seq);
    	int pro_seq = atoi(seq);//求出线程数
    	printf("id =%d\n", pro_seq);
    	cout++;
    	num -= 2;
    	printf("%s\n", buff);
    	printf("len=%d\n", strlen(buff));
    	cur_size += num;
    	printf("cur_size=%d\n", cur_size);
    
    	printf("线程id=%d\n", pro_seq);
    
    	int off = lseek(fd, pro_seq * 1000, SEEK_SET);//偏移到原本数据分片的地方
    	printf("偏移字节=%d\n", off);
    
    	write(fd, buff + 2, strlen(buff) - 2);
    	memset(buff, 0, sizeof(buff));
    	lseek(fd, 0, SEEK_SET);//指针重置
    	printf("-----------------------------------=--------------\n");
    	printf("cur_size=%d\n", cur_size);
    	if (cur_size >= size)
    	{
    		break;
    	}
    }

    多文件下载:

    为了实现多文件同时下载,采用了多客户端程序连接服务端的方式。前面提到过,服务端可以承受多客户端的连接,所以当有多个文件去下载时,表面上是由一个用户发出的请求,在内部实现时,模拟多用户去下载的过程。

    步骤:

    1.开启多个线程,将要下载的文件名传入各个线程;

    2.再线程函数中创建套接字去下载文件即可。

    运行截图:

     

    代码在git里面,需要借鉴的可以看。代码完全是本人自己的想法,如有不对或者错误请指正,交流加QQ:965829642.

    展开全文
  • 位于东软实习做的项目,基于Qt开发的高速公路智能收费系统。主要运用技术有,多线程,对数据库增删改查以及图片的上传及识别,保存信息与查询等。
  • 一、目的与要求做两个程序,实现文件收发发送端放两个按钮,...把文件接收下来,存进指定的某个目录里要能测试通过三个发送端同时发100M的文件,接收端能分别接收使用多线程实现二、工具/准备工作Qt开发环境webso...

    一、目的与要求

    做两个程序,实现文件收发

    发送端放两个按钮,点击后打开电脑目录选择所要传输的文件,选好以后,把文件名和路径显示在界面上,点击第二个按钮,把文件传到远程机器(或者虚拟机)上由接收端接收

    编写一接收端,把文件接收下来,存进指定的某个目录里

    要能测试通过三个发送端同时发100M的文件,接收端能分别接收

    使用多线程实现

    二、工具/准备工作

    Qt开发环境

    websocket传输协议库

    Win10_x64

    三、分析

    UI界面设计,使用qtdesigner工具,设计界面如下:

    Server端


    18423381-ba83f23ec1794f45.png

    源码下载地址:https://www.write-bug.com/article/1275.html

    展开全文
  • Http多线程下载模块,采用了文件内存映射等技术.本人是在vs2010 + qt5下实现。 qt4下我简单的写了下字符集的处理(未测试),可能会乱码.(qt5和qt4的差别还是有些大,可能要做些小的修改),程序不复杂,不算多,...
  • Qt 负责文件的读写 qml负责显示进度,文件读写在子线程中进行。代码可以直接运行。
  • qt5 tcp c/s 架构 文件传输多线程,断点续,注册、登陆验证,客户端操作服务器上的文件,文件权限
  • 局域网文件传输Qt+服务器客户端+多线程+TCP)

    千次阅读 热门讨论 2018-08-19 17:07:53
    本文章为Qt编程学习过程编写,仅供参考共同学习进步,请勿有其他用途!!! Qt版本为Qt Creator 5.7.0 ... 文章中对于代码部分不做解释,源代码中有...1、服务器端主要使用TCP和多线程进行编程。可以同时接受多个客...
  • 该程序是一个Http单文件多线程 、 断点续下载程序。qt4、qt5均可以编译通过,工程默认是qt5的工程。 (本人qt5.1.0 和 qt4.8.2 + vs2010下均测试过) 如果您想再qt4下编译,请: 1.修改工程工程的设置,设置好qt...
  • 1、客户端传输文件时采用多线程,新建一个线程用来传输文件,不使用界面线程; 2、程序只能使用MinGw-32位编译器编译,这是因为客户端文件传输进度条采用的是第三方自绘插件,受它的编译器限制; 3、客户端界面如...
  • 通过点击添加按钮,模拟接收新的文件传输请求,点击开始按钮,模拟实时接收文件传输进度并同步UI显示。开了一个线程产生文件及进度,发送信号给界面,界面收到信号后,将数据通过QtConcurrent::run异步处理。
  • QT多线程编程详解

    万次阅读 多人点赞 2019-04-24 22:08:20
    一、线程基础 1、GUI线程与工作线程 每个程序启动后拥有的第一个线程称为主线程,即GUI线程。QT中所有的组件类和几个相关的类只能工作在GUI线程,不能工作在次...二、QT多线程简介 QT通过三种形式提供了对线程...
  • Qt应用程序exec后就会生成一个线程,这个线程就是主线程,在GUI程序中也称为GUI线程。主线程也是唯一允许创建QApplication或QCoreAppliation对象,比并且可以对创建的对象调用exec()的线程,从而进入事件循环。 在...
  • 发送端5个线程发送数据,接收端主线程接收到数据放入循环队列,同时接收端一个子线程从队列中取出数据并写入文件,但总丢包,不知道问题出在哪?
  • 客户端给服务器发送文件,服务器进行接收文件的简单操作 1. 服务器 1. 创建QTcpServer 类的对象 QTcpServer * server = new QTcpServer(this); 2. 进行监听 bool QTcpServer::listen(const QHostAddress &...
  • QT编写多线程TCP文件接收服务器
  • 为此 自学了一下多线程 目的做一个的并行处理。我这里只需要接收数据就好。 QT 需要继承一个 QThread 类 来运行线程 1. mythread.h 文件 //mythread.h 文件 #ifndef MYTHREAD_H #define MYTHREAD_H #include <...
  • C++/Qt 多线程编程分析

    2019-07-23 23:28:28
    为什么要使用多线程?什么时候必须使用?使用多线程的烦恼?在子线程中使用定时器,碰上子线程阻塞呢?
  • Qt多线程之间传递参数

    千次阅读 2018-03-01 14:18:47
    多线程间需要传递信号给另外一个线程的槽,而信号和槽所使用的参数为非QObject,无论其是stl的标准库类型还是其他类型,都必须先注册,否则信号发送了,槽将会始终不调用。也就是说qt的槽参数一定要是QOject类型的...
  • 目标:用户端:linux(arm平台),完成文件的传输服务器:windows ,使用多线程的文件的接收实现无线的文件传输功能用户端程序,用标准的socket完成文件传输的功能,代码如下://Linux下网络编程,客户端程序代码//...
  • Qt 多线程/多窗口 参数传递

    千次阅读 2018-04-14 23:39:39
    · 重要的事情放前边说 只能用 信号 - 槽 机制 只能用 信号 - 槽 机制 只能用 信号 - 槽 机制 自己定义的数据结构要另当别论 自己定义的数据结构要另当别论 ...Qt支持的数据类型如 QString、int、dou...
  • qt多线程信号槽传输方式

    千次阅读 2019-01-08 01:13:43
    //简单介绍一下QT信号与槽的连接方式: //Qt::AutoConnection表示系统自动选择相应的连接方式,如果信号与槽在同一线程,就采用Qt::DirectConnection, //如果信号与槽不在同一线程,将采用Qt::QueuedConnection的...
  • 源代码我在代码里面都有非常详细的注释,所以就直接放上代码啦1 客户端头文件 mainwindow.hifndef MAINWINDOW_Hdefine MAINWINDOW_Hinclude QT_BEGIN_NAMESPACEnamespace Ui { class MainWindow; }QT_END_NAMESPACE...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,412
精华内容 2,564
关键字:

qt多线程文件传输