IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> QT笔记文件传输(tcp)功能介绍,局域网速度极快 -> 正文阅读

[网络协议]QT笔记文件传输(tcp)功能介绍,局域网速度极快

因为是我刚接触qt不久学习的过程,所以有对实现功能的前提基础有一些介绍。我介绍的是一个实现过程,有核心的实现代码,在我测试后发现在局域网内传输速度大于200m/s时发送较大文件可能会稍有卡顿,不过等一会儿发送完毕后就正常了,如果在公网上传输则取决于你的传输速度。

首先要建立一个tcp的连接。

    fileSocket->abort();
    fileSocket->connectToHost(IP, 8888);
    if(!fileSocket->waitForConnected(1000))
    {
        qDebug() << "fileSocket Connection failed!"<<"error"<<fileSocket->error();
        this->close();
        return;
    }
    qDebug() << "fileSocket Connect successfully!";

这个是客户端片段,比较简单,相关博客非常多,客户端发起连接请求后,服务端监听这个端口就好了,这个IP则是服务端的ip地址。

    TcpServer ser;   //这个是我重写的类   qt原始的类是QTcpServer
    ser.listen(QHostAddress::Any,8888);

一、服务端部分:

服务端部分我重写了QTcpSocket类目的是为了多客户端连接,这个先不说

这是服务端部分发送和接收的槽函数和一些参数初始化,(readyRead()信号需要注意的是并不是客户端write一次就会触发一次)

    connect(this, SIGNAL(readyRead()), this, SLOT(updateFileProgress()));                       
       //接受文件的槽函数
    connect(this, SIGNAL(bytesWritten(qint64)), this, SLOT(updateFileProgress(qint64)));          
     //发送文件的槽函数

    bytesWritten = 0;             //已发送的文件字节数大小用来判断是否发送完毕
    perDataSize = 64 * 1024;      //每次发送的最大字节数
    bytesReceived = 0;            //已接收的文件字节数大小
    totalBytes = 0;               //文件名和文件实际内容的总大小
    filenameSize = 0;             //文件名大小

接收槽函数(updateFileProgress()//receive)具体实现

 QString ip,ordertype;
    QDataStream inFile(this);
    inFile.setVersion(QDataStream::Qt_4_8);
    if (bytesReceived <= sizeof(qint64)* 2)
    {
        if ((this->bytesAvailable() >= (sizeof(qint64)) * 2) && (filenameSize == 0))  
//首次接收文件总大小和文件名大小
        {
            inFile >> totalBytes >> filenameSize;
            bytesReceived += sizeof(qint64)* 2;
        }
        if ((this->bytesAvailable() >= filenameSize) && (filenameSize != 0))
        {
            //这里接收文件名和发送方ip相关信息的部分  如果
            inFile >> filename>>ip;
            bytesReceived += filenameSize;
            if(filename=="*****")
            {
                //这里可以对文件名进行判断  然后选择相应的文件保存目录也可以利用getSaveFileName手动选取目录
            }
            localFile = new QFile(filename);
            if (!localFile->open(QFile::WriteOnly))
            {

                qDebug() << "Server::open file error!";
                return;
            }
        }
        else
        {
            QString other=this->readAll();
        //这里可以根据接收内容执行不是文件传输时需要执行的操作
        }
    }
    if (bytesReceived < totalBytes)    //文件未传输完毕时持续接收剩余要接收的内容
    {
        bytesReceived += this->bytesAvailable();
        inBlock = this->readAll();
        localFile->write(inBlock);
        inBlock.resize(0);
    }
    //qDebug()<<totalBytes;
    //qDebug()<<bytesReceived;
    if (bytesReceived == totalBytes)//内容发送完毕后释放文件
    {
        qDebug()<<"Receive file successfully!";
        bytesReceived = 0;
        totalBytes = 0;
        filenameSize = 0;
        localFile->close();
        //filesocket->close();
    }

发送部分与接收部分是对应的,分两部分,一个是首次发送部分,和后续文件实际内容发送部分,首次发送部分包括发送方ip,文件名,文件总大小

首次发送函数具体实现

    QString ip;
    QList<QHostAddress> NetList = QNetworkInterface::allAddresses(); //取得ip等全部信息
    for(int i=0;i<NetList.count();i++)
    {
        ip.append(NetList.at(i).toString());
    }
    this->localFile = new QFile(filename);               //这个filname是发送目标文件的目录
    if (!localFile->open(QFile::ReadOnly))
    {
        return;
    }
    this->totalBytes = localFile->size();
    QDataStream sendout(&outBlock, QIODevice::WriteOnly);//用QDataStream类做缓冲区
    sendout.setVersion(QDataStream::Qt_4_8);
    QString FileName = filename.right(filename.size() - filename.lastIndexOf('/') - 1);
    //文件名
    
    sendout << qint64(0) << qint64(0) << FileName;  
    sendout<<ip;
    totalBytes += outBlock.size();
    sendout.device()->seek(0);
    sendout << totalBytes << qint64((outBlock.size() - sizeof(qint64)* 2));
    
    bytestoWrite = totalBytes - this->write(outBlock);
    outBlock.resize(0);

接着是后续发送槽函数(updateFileProgress(qint64 numBytes))具体实现

       bytesWritten += (int)numBytes;

        if (bytestoWrite > 0)
        {
            outBlock = localFile->read(qMin(bytestoWrite, perDataSize));
            bytestoWrite -= ((int)fileSocket->write(outBlock));
            outBlock.resize(0);
        }
        else
        {
            localFile->close();  //发生某些错误直接结束
        }
         
        //progressBar->setMaximum(totalBytes);//这里可以用来显示已经发送的大小
        //progressBar->setValue(bytesWritten);

        if (bytesWritten == totalBytes) //发送完毕
        {
            bytesWritten = 0;
            localFile->close();
            //fileSocket->close();
        }

二、客户端部分

客户端部分文件传输的部分跟服务端是一样的,从文件传输的角度来看不分服务和客户端,原来的完整代码已经没有了,现在是临时写出来的。谢谢大家~

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-02-16 13:30:42  更:2022-02-16 13:33:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:02:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码