Qt网络编程之TCP通信(二)文件传输

9 篇文章 0 订阅
2 篇文章 1 订阅

一、流程图

上一篇博客介绍了Qt下Tcp通信流程,并实现了简单的文本传输,本文主要介绍Tcp文件传输过程。
流程图如下:

  1. 服务器
Created with Raphaël 2.2.0 开始 创建监听套接字对象 和通信套接字对象 监听套接字监听指定的Ip和端口 是否有新的 连接请求? 获取客户端信息 选择文件,并 发送文件信息 是否收 到应答? 发送文件 是否发 送完成? 结束 yes no yes no yes no
  1. 客户端
Created with Raphaël 2.2.0 开始 创建通信套接字对象 连接到指定IP和端口 是否接收 到数据? 是否是第一 帧数据? 发送应答信息 选取保存路径 数据写入文件 文件是否写 入完毕? 结束 yes no yes no yes no

二、项目创建

  1. 服务器
    在这里插入图片描述
    在这里插入图片描述
    1)创建监听套接字和通信套接字:

    tcpServer = new QTcpServer(this);
    tcpSocket = NULL;
    

    2)监听是否有新的连接请求:

     tcpServer->listen(QHostAddress::Any,6666);
     connect(tcpServer,SIGNAL(newConnection()),this,SLOT(HaveNewConnection()));
    

    3)获取客户端的信息:

     void Widget::HaveNewConnection()
     {
         tcpSocket = tcpServer->nextPendingConnection();
         QString ip = tcpSocket->peerAddress().toString();
         quint16 port = tcpSocket->peerPort();
         QString str = QString("[%1:%2] 成功连接").arg(ip).arg(port);
         connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(RcvData()));
         QMessageBox::information(this,"Info",str,QMessageBox::Ok);
     }
    

    4)选择文件

    void Widget::on_pushButton_choose_clicked()
    {
        QString filePath = QFileDialog::getOpenFileName(this,"open","../");
        if(!filePath.isEmpty())
        {
            fileName.clear();
            fileSize = 0;
            sendSize = 0;
            QFileInfo info(filePath);
            fileName = info.fileName();
            fileSize = info.size();
            file.setFileName(filePath);
            if(file.open(QIODevice::ReadOnly))
            {
                ui->textEdit->setText(tr("打开文件 ").append(filePath).append("\n"));
            }
            else
            {
                qDebug()<<"文件打开失败";
            }
        }
        else
        {
            qDebug()<<"文件路径出错";
        }
    }
    

    其中fileSize是文件总的字节数,sendSize是已经发送的字节数,打开文件时二者先清零,当sendSize == fileSize时表明文件已经发送完成。
    5)发送文件信息

    void Widget::on_pushButton_send_clicked()
    {
        QString head = tr("%1##%2").arg(fileName).arg(fileSize);
        quint64 len = tcpSocket->write(head.toUtf8().data());
        if(len<=0)
        {
            qDebug()<<"头部信息发送失败 ";
            file.close();
        }
    }
    

    包括文件名和文件大小,这一帧数据应独立于文件数据之外,换句话说,应该确定客户端收到文件信息之后再发送文件数据。
    6)发送文件数据

    void Widget::SendFile()
    {
        qint64 len = 0;
        do{
            char buf[64*1024] = {0};
            len = 0;
            len = file.read(buf,sizeof(buf));
            len = tcpSocket->write(buf,len);
            sendSize += len;
        }while(len > 0);
        if(sendSize == fileSize)
        {
            ui->textEdit->setText("文件发送完毕 \n");
            file.close();
            tcpSocket->disconnect();
            tcpSocket->close();
        }
    }
    
  2. 客户端
    在这里插入图片描述
    在这里插入图片描述
    1)创建通信套接字,并监听是否接收到数据

    tcpSocket = new QTcpSocket(this);
    connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(RcvFile()));
    

    2)连接到指定服务器IP和端口

    void Client::on_pushButton_connect_clicked()
    {
        QString ip = ui->lineEdit_ip->text();
        quint16 port = ui->lineEdit_port->text().toInt();
        tcpSocket->connectToHost(ip,port);
    }
    

    3)接收数据并处理

    void Client::RcvFile()
    {
        QByteArray buf = tcpSocket->readAll();
        if(isStart)
        {
            isStart = false;
            QString dir = QFileDialog::getExistingDirectory(this,"选择文件夹 ","./"); 
            fileName = dir.append("/").append(QString(buf).section("##",0,0));
            fileSize = QString(buf).section("##",1,1).toInt();
            QString info = tr("文件名称:").append(QString(buf).section("##",0,0)).append("\n")
                      .append("保存路径:").append(dir).append("   \n")
                      .append("文件大小:").append(QString::number(fileSize/1024.0/1024.0,'f',2)).append("Mb");
            rcvSize = 0;
            qDebug()<<fileName<<fileSize;
            ui->textEdit_filemsg->setText(info);
            tcpSocket->write(QString(buf).section("##",0,0).toUtf8().data());
            file.setFileName(fileName);
            if(file.open(QIODevice::WriteOnly))
            {
    
            }
            else
            {
                qDebug()<<"write only error";
            }
    
            mTime.start();
        }
        else
        {
            qint64 tmp = 0;
            static qint64 cnt = 0;
            cnt++;
            qint64 len = file.write(buf);
            rcvSize += len;
            tmp += len;
            int progress = (int)((rcvSize*1.0)/(fileSize*1.0) * 100);
            if(cnt%10 == 0)
            {
                float speed;
                QTime current_time = QTime::currentTime();
                int msec = current_time.msec();
                if(last_time != 0)
                {
                    if(msec<last_time)
                        speed = tmp * 1000.0/((msec + 1000-last_time)*1024.0*1024.0);
                    else if(msec == last_time)
                        speed = 100.0;
                    else
                        speed = tmp * 1000.0/((msec-last_time)*1024.0*1024.0);
                }
                last_time = msec;
                tmp = 0;
                ui->progressBar->setValue(progress);
                if(cnt%100 == 0)
                    ui->label_speed->setText(QString::number(speed,'f',2).append("Mb/s"));
    
            }
            if(rcvSize == fileSize)
            {
                QString str = ("下载时间:");
                ui->textEdit_filemsg->append(str.append(QString::number(mTime.elapsed()/1000.0,'f',1)).append("s"));
                ui->progressBar->setValue(100);
                ui->label_speed->setText("0.00");
                file.close();
                QMessageBox::information(this,"完成","文件接收完成");
                tcpSocket->disconnectFromHost();
                tcpSocket->close();
                isStart = true;
            }
        }
    }
    

    首先判断数据是不是第一帧,如果是,则说明是文件信息,对应应该选择文件存储路径并向服务器发送应答(服务器接收到应答才开始发送文件);如果不是第一帧 则说明是文件数据,对应执行写文件操作,另外还有一些进度和速度显示操作。

    三、实例测试

    由于Qt的跨平台特性,项目中将客户端移植到虚拟机中的linux系统下,服务器留在windows中,测试传输效果如下:在这里插入图片描述
    项目连接:https://gitee.com/Mr-Yslf/BlogResources.git

### 回答1: qt tcp通信v2.zip是一个Qt程序文件,用于实现TCP通信功能。 Qt是一个跨平台的C++应用程序开发框架,可以方便地开发图形用户界面(GUI)和网络通信功能。TCP是一种可靠的传输协议,常用于实现网络通信qt tcp通信v2.zip包含了一个示例程序,是基于Qt框架的TCP通信的实现。它可能包含了与网络通信相关的源代码文件、进制可执行文件、配置文件等资源。 使用Qt进行TCP通信,可以方便地进行客户端和服务器端之间的数据传输。通过TCP协议,可以建立可靠的连接,实现稳定的数据传输。在Qt的API中,提供了一些类和函数,可以方便地创建TCP服务器和客户端,进行数据传输和接收。 使用qt tcp通信v2.zip,我们可以学习如何在Qt框架的基础上,实现TCP通信的功能。可以学习如何创建一个简单的TCP服务器,监听指定端口,并接收客户端的连接请求。也可以学习如何创建一个TCP客户端,与服务器建立连接,并向服务器发送数据。 通过学习qt tcp通信v2.zip,我们可以了解Qt框架的网络编程能力,学习如何使用Qt进行网络通信的开发。这对于需要实现网络通信功能的应用程序开发来说,是非常有帮助的。 ### 回答2: "qt tcp通信v2.zip"是一个文件压缩包,它包含了关于QT框架下TCP通信的相关实例代码和资源。 QT是一个跨平台的C++应用程序开发框架,它提供了丰富的功能和工具,用于开发图形用户界面和网络应用程序等。而TCP通信是一种面向连接的网络通信协议,它可以在不同的设备之间进行可靠的数据传输。 在这个文件压缩包中,我们可以找到一些用QT框架实现TCP通信的示例代码,这些代码可以帮助开发人员理解和掌握TCP通信的基本原理和操作。此外,压缩包还可能包含一些必要的资源文件,如图标、配置文件等,以帮助使用者更方便地开发和测试应用程序。 要使用这个文件压缩包,我们首先需要解压缩它。解压后,我们可以使用QT开发环境打开这些示例代码,通过阅读和分析代码,了解QT框架如何实现TCP通信的功能。 同时,我们还可以基于这些示例代码进行修改和扩展,根据自己的需求开发更复杂和功能强大的TCP通信应用程序。 总之,"qt tcp通信v2.zip"是一个提供QT框架下TCP通信实例代码和资源的文件压缩包,通过使用它,我们可以学习和应用QT框架的TCP通信功能。 ### 回答3: "qt tcp通信v2.zip"是一个用于实现Qt TCP通信的代码文件压缩包。Qt是一种跨平台的应用程序开发框架,它提供了丰富的类库和工具,用于开发图形界面和网络应用程序等。 该压缩包中的代码主要涉及TCP通信的功能实现。TCP传输控制协议)是一种面向连接的可靠的数据传输协议,常用于在计算机网络中实现数据通信Qt提供了用于创建TCP套接字(socket)的类库,并包含了一些常用的通信函数和信号槽机制,用于发送和接收数据。这个压缩包中的代码文件应该包含了使用Qt实现TCP通信的必要函数和类。 通过使用这个压缩包中的代码,我们可以利用Qt提供的TCP套接字类库,完成两台计算机之间的数据传输。比如,可以实现一个客户端和服务器端的通信,或者两台客户端之间的通信Qt TCP通信v2.zip提供了一个简单方便的方式来构建和管理TCP连接,并实现数据的发送和接收。用户可以根据自己的需求,修改和扩展这些代码,以满足特定的通信需求。 总之,Qt TCP通信v2.zip是一个包含用于实现Qt TCP通信的代码文件压缩包,可以帮助开发者轻松地在Qt框架下实现TCP通信的功能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值