基于QTcpSocket的网络文件传输

 目标要求:

        本实验主要是有一个服务器和客户端,服务器可以选择本地的文件,然后发给客户端,客户端可以选择保存的路径。同时在两边传输文件的过程中,使用进度条控件来提示文件传输进度。

主要控件有LineEdit PushButton progressBar.

涉及知识:

        主要是基本控件的使用,TCP的服务器和客户端的通信流程,文件的读写,QT中信号与槽,Qt中定时器的使用,文件对话框的使用,进度条控件的使用

效果图展示:

 完成文件接收发效果:

查看文件传输是否完全正确:  

该项目实现基本讲解:

 服务器流程图:

客户端流程图:  

代码实现:

服务器:

1.添加所需要的头文件以及所需成员和槽函数

注意在使用网络模块需要在xx.pro添加QT+ =network

#include <QTcpServer>		
#include <QTcpSocket>
#include <QDebug>
#include <QFile>
#include <QFileDialog>
#include <QPushButton>
#include <QFileInfo>
#include <QHostAddress>
#include <QTimer>

private:
    Ui::Server *ui;
    QTcpServer *server; //服务器对象
    QTcpSocket *socket; //网络套接字
    QByteArray data;    //接收数据缓冲区
    QTimer *timer;      //定时器对象
    QFile sendfile;     //文件对象
    QString file;       //文件路径
public slots:
    void chose_file(void);  //选择文件传输
2.在构造函数中添加服务器端监听IP和端口,套接字的消息读写的信号与槽代码
    setWindowTitle("服务器");
    resize(600,150);
    //创建对象
    server=new QTcpServer(this);
    socket=new QTcpSocket(this);
    timer=new QTimer(this);
    ui->progressBar->setValue(0);

    //监听IP和端口
    if(!server->listen(QHostAddress("10.163.1.116"),8888))
    {
        qDebug()<<"服务器监听错误"<<server->errorString();
    }
    else {
        qDebug()<<"服务器监听成功";
    }
    //当有新的连接时
    connect(server,&QTcpServer::newConnection,[=](){
        socket=server->nextPendingConnection();
        qDebug()<<"有新的客户端连接!";
    });
    //选文件和绑定客服端IP和端口
    connect(ui->chosefile_btn,&QPushButton::clicked,this,&Server::chose_file);
 3.槽函数实现
void Server::chose_file()
{
    //发送文件
    //获取文件
    file =QFileDialog::getOpenFileName(this,"打开文件","D:\\Linux_qt\\ARM\\笔记");
    qDebug()<<"文件路径:"<<file;
    ui->filename_edit->setText(file);

    //获取文件信息
    QFileInfo info(file);
    QString filename=file.section('/',-1);
    qDebug()<<"文件名称:"<<filename.toUtf8().data()<<"文件大小:"<<info.size();
    //发送文件名称和文件大小
    QString sendFileInfo=filename+"@"+QString::number(info.size());
    qDebug()<<"sendFileInfo:"<<sendFileInfo;
    socket->write(sendFileInfo.toUtf8());

    //接收是否开始发送文件的信息
    connect(socket,&QTcpSocket::readyRead,[=](){
        data=socket->readAll();
        qDebug()<<"test1:"<<data.data();
        if(QString(data)=="我已经接收到文件信息,请开始发送文件")
        {
            //打开文件
            //QFile sendfile(file);
            sendfile.setFileName(file);
            //设置打开方式
            sendfile.open(QIODevice::ReadOnly);
            timer->start(100);
            connect(timer,&QTimer::timeout,[=](){
                // 发送文件内容
                static qint64 sentSize = 0;
                if(sentSize<info.size())
                {
                    QByteArray buffer = sendfile.read(40960);
                    qint64 ret = socket->write(buffer);
                    if (ret < 0)
                    {
                        qDebug() << "发送文件失败:" << socket->errorString();
                    }
                    sentSize += ret;
                    //qDebug()<<"发送了"<<ret<<"字节数据";
                    ui->progressBar->setValue((qint64)(sentSize)*100/info.size());
                }
                else
                {
                    timer->stop();
                    sendfile.close();
                }
            });
        }
    });

}

客户端: 

1.添加头文件和成员变量以及槽函数声明
#include <QTcpSocket>
#include <QDebug>
#include <QFile>
#include <QFileDialog>
#include <QPushButton>
#include <QFileInfo>
#include <QHostAddress>

private:
    Ui::Client *ui;
    QTcpSocket *socket;
    QString filename; // 保存文件名
    QString savePath; //保存路径
    qint64 fileSize; // 保存文件大小
    QFile file;      //文件对象
    QByteArray data;  //信息缓冲区
    int flag;   //标志位
public slots:
    void save_file(void);
 2.构造函数中添加连接服务器的代码,以及接收服务器发过来的消息和文件内容,将文件内容写入到创建的新文件中,设置接收文件进度条的状态
    setWindowTitle("客户端");
    resize(600,150);
    ui->progressBar->setValue(0);
    socket=new QTcpSocket(this);
    flag=0;
    //连接到服务器
    socket->connectToHost(QHostAddress("10.163.1.116"),8888);
    // 当连接成功时
    connect(socket, &QTcpSocket::connected, [=]() {
        qDebug() << "已连接到服务器";
    });

    // 当接收到数据时
    connect(socket, &QTcpSocket::readyRead, [=]() {
        data= socket->read(40960);
        static quint64 readBytes=0;
        if(flag)
        {
            // 如果接收到的数据大小小于文件大小,接收文件
            if (readBytes != fileSize)
            {
                file.write(data);
                readBytes += data.size();
                //qDebug()<<"收到文件大小为"<<readBytes;
                ui->progressBar->setValue((qint64)readBytes*100/fileSize);
            }
            else
            {
                file.close();
                qDebug() << "文件接收完毕";
            }
        }
    });
    //选择保存文件路径
    connect(ui->savefile_btn,&QPushButton::clicked,this,&Client::save_file);
3、槽函数实现
void Client::save_file()
{
    // 处理接收到的数据
    if (filename.isEmpty() && fileSize == 0)
    {
        QString fileInfo = QString(data);
        filename=fileInfo.section('@',0,0);
        fileSize=fileInfo.section('@',1,1).toLongLong();

        qDebug()<<"接收到的文件名:"<<filename<<"接收到的文件大小:"<<fileSize;
        //获取保存的路径
        savePath = QFileDialog::getExistingDirectory(this, "选择保存路径", QDir::homePath());
        if (!savePath.isEmpty())
        {
            // 用户选择了保存路径
            savePath+="/";
            savePath+=filename;
            qDebug() << "选择的保存路径:" <<savePath;
            ui->filename_edit->setText(savePath);
        }
        else
        {
            // 用户取消了选择
            qDebug() << "用户取消选择保存路径";
            return;
        }
        file.setFileName(savePath); // 替换为你要保存的文件路径
        if (!file.open(QIODevice::WriteOnly))
        {
            qDebug() << "无法创建文件";
            return;
        }
        socket->write("我已经接收到文件信息,请开始发送文件");
        flag=1;
    }
}

总结:

        本练习比较基础,只是设计网络通信,文件的基本传输,基本控件的使用,可以是初学者练习。

优化改进的地方有:

        1.可以增加服务器和客户端聊天功能

        2.可以实现文件多次发送接收,不仅只限于一次

        3.可以同时传输多个文件

最后如果有需要源代码的伙伴:链接在下方。给博主点一点关注吧。

https://pan.baidu.com/s/1lot7iIOui2PLyvY6Q_KPkA?pwd=JC66 提取码:JC66

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Qt Quick 是一个用于创建现代、高性能用户界面的框架,而 QTcpSocketQt 框架的一个类,用于实现基于 TCP 协议的网络通信。QML 是 Qt Quick 的声明式语言,可以轻松创建用户界面和实现逻辑交互。 在 QML 中使用 QTcpSocket,需要先在 QML 文件中导入 QtNetwork 模块,然后通过创建一个 QTcpSocket 实例来与服务器进行连接。可以使用的方法包括 connectToHost() 连接到指定的主机和端口,write() 发送数据,以及 read() 接收数据。可以通过 signals 信号来处理与服务器的连接状态、数据传输等事件。 假设我要在 QML 中实现一个客户端应用,与服务器进行通信。首先,需要在 QML 文件中导入 QtNetwork 模块: import QtQuick 2.15 import QtQuick.Controls 2.15 import QtNetwork 2.15 然后,创建一个 QTcpSocket 实例: QTcpSocket { id: tcpSocket } 接下来,可以通过以下代码连接到服务器tcpSocket.connectToHost("127.0.0.1", 12345) 其中,"127.0.0.1" 是服务器的 IP 地址,12345 是服务器的端口号。 可以通过以下信号处理服务器连接状态: onConnected: console.log("Connected to server") onDisconnected: console.log("Disconnected from server") onErrorOccurred: console.log(errorString) 在连接成功后,可以使用 write() 方法发送数据给服务器tcpSocket.write("Hello, server!") 可以使用 read() 方法接收服务器发送的数据: console.log("Received data: " + tcpSocket.readAll()) 需要注意的是,在使用 QTcpSocket 时,需要保持 QML 事件循环不阻塞,可以使用异步方式处理数据的读写,避免界面冻结。 总之,使用 QTcpSocket 可以在 QML 中实现基于 TCP网络通信,与服务器进行连接、发送数据和接收数据。这样,我们就可以在 QML 中轻松实现网络功能,并与远程服务器进行交互。 ### 回答2: QML是一种基于Qt框架的声明性语言,用于在Qt应用程序中创建用户界面。它提供了一种简洁和直观的方法来定义图形元素和交互行为。QTcpSocketQt提供的一种用于处理TCP连接的类,它允许应用程序发起和接收TCP连接,以及发送和接收数据。在QML中使用QTcpSocket时,可以通过在QML代码中创建和配置QTcpSocket的实例来实现与TCP服务器的通信。 要使用QTcpSocket在QML中进行TCP通信,首先要导入Qt网络模块,然后在QML中创建一个QTcpSocket的实例。可以使用其提供的函数来连接服务器、发送和接收数据。例如,可以通过调用connectToHost函数来连接到远程服务器,通过调用write函数来发送数据,通过调用readyRead函数来接收服务器返回的数据。 在与服务器进行通信时,可以使用QML中的属性和信号槽机制来处理数据的传输和处理。例如,可以使用text属性来存储接收到的数据,并使用onReadyRead信号来触发数据的接收和处理。 在QML中使用QTcpSocket进行TCP通信时,需要注意以下几点: 1. 需要适当处理连接建立和断开的事件,以确保连接的稳定性和可靠性。 2. 需要处理数据的分割和组装,以确保正确解析接收到的数据。 3. 需要处理异常和错误情况,例如连接超时、连接中断等,以提供良好的用户体验和错误处理机制。 总之,通过使用QTcpSocket,结合QML的声明性特性,我们可以轻松实现TCP通信功能,并将其集成到QML应用程序中。这为开发具有网络通信功能的现代应用程序提供了便利和强大的工具。 ### 回答3: QML是一种用于创建跨平台用户界面的语言,而QTcpSocketQt框架中的一个类,用于实现TCP协议的客户端和服务器端之间的通信。 QTcpSocket提供了一组用于连接、读写数据和处理网络错误的方法和信号。在QML中,可以通过使用Qt的C++库和在QML文件中注册的自定义类型来访问和使用QTcpSocket。 首先,需要在QML文件中导入Qt网络模块,例如: ``` import Qt.Network 2.15 ``` 然后,可以创建一个QTcpSocket对象,并连接到服务器。以下是一个简单的例子: ``` import QtQuick 2.15 import QtQuick.Controls 2.15 import Qt.Network 2.15 ApplicationWindow { visible: true width: 400 height: 300 title: "QTcpSocket Example" Page { TextArea { id: outputText anchors.fill: parent readOnly: true } Button { text: "Connect" onClicked: { socket.connectToHost("127.0.0.1", 1234) } } } QTcpSocket { id: socket onConnected: { outputText.append("Connected to server!") } onError: { outputText.append("Error: " + errorString()) } onReadyRead: { var data = readAll() outputText.append("Received data: " + data) } } } ``` 在这个例子中,当点击按钮时,会尝试连接到IP地址为"127.0.0.1",端口号为1234的服务器。如果连接成功,会在输出文本区域显示"Connected to server!",如果发生错误,会显示错误信息。当接收到数据时,会将数据追加到输出文本区域。 需要注意的是,QTcpSocket的方法和信号可以被直接访问和使用,例如连接到相应的信号,并在接收到数据时进行相应的处理。此外,还可以设置缓冲区大小、写入数据等。 总之,QML和QTcpSocket可以结合使用,实现TCP协议的网络通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值