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传输文件

源码下载点这

在这里插入图片描述

1、简介

界面如上,近期研究了一下,参考网上别人程序自己做了修改,没有用多线程所以在传输时候有时候会出现卡顿,该程序只适合传小文件,因为定义文件大小是quint32类型,理论上只能传4G以下的文件,文件保存路径程序中有显示

2、操作流程

1、监听
2、连接
3、打开文件
4、发送
文件保存在Receive目录下
在这里插入图片描述
在这里插入图片描述

3、源码

#ifndef UPDATACLIENT_H
#define UPDATACLIENT_H

#include <QWidget>
#include <QTcpSocket>
#include <QFile>
#include <QString>

namespace Ui {
class UpdataClient;
}

class UpdataClient : public QWidget
{
    Q_OBJECT

public:
    explicit UpdataClient(QWidget *parent = nullptr);
    ~UpdataClient();

public slots:
    void ClientReadError(QAbstractSocket::SocketError);
    void ClinetReadData();

private slots:
    void on_butConnect_clicked();

    void on_buttonSend_clicked();

    void on_buttonSelect_clicked();

private:
    Ui::UpdataClient *ui;

    quint16 port;
    QString ip;

    QTcpSocket* m_tcpSocket;
    QFile *m_file; //需要发送的文件对象
    QString fileName;

    quint32 fileSize;
    quint32 fileLoad;

    bool socketFlag;


};

#endif // UPDATACLIENT_H

#include "updataclient.h"
#include "ui_updataclient.h"
#include <QFileDialog>
#include <QFileInfo>
#include <string.h>
#include <QThread>


UpdataClient::UpdataClient(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::UpdataClient)
{
    ui->setupUi(this);

    port = 8888;
    ip = "192.168.1.250";
    m_tcpSocket = nullptr;
    this->m_tcpSocket=new QTcpSocket(this);
    socketFlag = false;
    ui->progressBar->setValue(0);
    ui->buttonSend->setEnabled(false);
    ui->buttonSelect->setEnabled(false);

    m_file = new QFile(this);

}

UpdataClient::~UpdataClient()
{
    if(m_file->isOpen()==true)
    {
        m_file->close();
        m_file->deleteLater();
    }

    if(socketFlag == true)
    {
        m_tcpSocket->disconnect();//断开信号槽
        m_tcpSocket->abort();//终止
        m_tcpSocket->close();//释放
        m_tcpSocket->deleteLater();
    }

    delete ui;
}

void UpdataClient::on_butConnect_clicked()
{
    if(socketFlag == false)
    {
        m_tcpSocket->connectToHost(ip,port);
        connect(m_tcpSocket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(ClientReadError(QAbstractSocket::SocketError)));
        //等待连接
        if (m_tcpSocket->waitForConnected(1000))
        {
            connect(m_tcpSocket,SIGNAL(readyRead()),this,SLOT(ClinetReadData()));
            socketFlag = true;
            ui->buttonSelect->setEnabled(true);
            //更新UI
            ui->TcpMessage->append("已连接服务器"+QString("[%1:%2]").arg(ip).arg(port));
            ui->butConnect->setText("断开");
        }
        else//连接失败
        {
            m_tcpSocket->disconnect();
            m_tcpSocket->close();
            socketFlag=false;
            ui->buttonSend->setEnabled(false);
            ui->buttonSelect->setEnabled(false);
            ui->TcpMessage->append("连接失败"+QString("[%1:%2]").arg(ip).arg(port));
            ui->butConnect->setText("连接");
        }
    }
    else if(socketFlag== true)
    {
        m_tcpSocket->disconnect();//断开信号槽
        m_tcpSocket->abort();//终止
        m_tcpSocket->close();//释放
        socketFlag=false;
        //更新UI
        ui->TcpMessage->append("已断开服务器"+QString("[%1:%2]\r\n").arg(ip).arg(port));
        ui->butConnect->setText("连接");
        ui->buttonSend->setEnabled(false);
        ui->buttonSelect->setEnabled(false);
    }
}

//tcp客户端读取数据
void UpdataClient::ClinetReadData()
{
    QByteArray ba = m_tcpSocket->readAll();
    QString data;

    data=QString::fromLocal8Bit(ba);

    //显示
    ui->TcpMessage->insertPlainText(data);
    ui->TcpMessage->moveCursor(QTextCursor::End);
}

//tcp客户端发生错误
void UpdataClient::ClientReadError(QAbstractSocket::SocketError)
{
    QString err=QString("发生错误:%1").arg(m_tcpSocket->errorString());
    ui->TcpMessage->append(err);
    m_tcpSocket->disconnect();//断开所有信号
    m_tcpSocket->close();//终止socket连接
    socketFlag=false;
    ui->buttonSend->setEnabled(false);
    ui->buttonSelect->setEnabled(false);
    //更新UI
    ui->TcpMessage->append("已断开服务器"+QString("[%1:%2]").arg(ip).arg(port));
    ui->butConnect->setText("连接");

}

void UpdataClient::on_buttonSend_clicked()
{
    //1.发送文件头  格式:文件名###文件大小
   unsigned char tempStr[4*1024];
   memset(tempStr,0,4*1024);
   tempStr[0]='#';
   tempStr[1]='#';
   tempStr[2]='#';
   tempStr[3]=static_cast<unsigned char>(fileSize>>24);
   tempStr[4]=static_cast<unsigned char>(fileSize>>16);
   tempStr[5]=static_cast<unsigned char>(fileSize>>8);
   tempStr[6]=static_cast<unsigned char>(fileSize);
   tempStr[7]='#';
   QByteArray ba;
   char *pstr = nullptr;
   ba = fileName.toUtf8();
   pstr = ba.data();
   memcpy(tempStr+8,pstr,static_cast<size_t>(ba.size()));

   m_tcpSocket->write(reinterpret_cast<char *>(tempStr),4*1024);
   m_tcpSocket->flush();
   qint64 len = 0;
   fileLoad = 0;
   do{
       //每次发送4KB
       char buf[4*1024] = {0};
       len = 0;
       len = m_file->read(buf, sizeof(buf));
       len = m_tcpSocket->write(buf, len);
       fileLoad += len;
       ui->progressBar->setValue(fileLoad/1024);
   }while (len > 0);
   m_file->close();
   ui->buttonSelect->setEnabled(true);
   ui->buttonSend->setEnabled(false);
}

void UpdataClient::on_buttonSelect_clicked()
{
    //初始化文件属性
    QString filePath = QFileDialog::getOpenFileName(this, "Open", "../");
    if(!filePath.isEmpty())
    {
        QFileInfo info(filePath);
        fileName = info.fileName();
        fileSize = static_cast<quint32>(info.size());
//        qDebug()<<fileName<<fileSize;

        m_file->setFileName(filePath);

        if(m_file->open(QIODevice::ReadOnly))
        {
            ui->TcpMessage->append(QString("FileName:%1 \n\nFileSize:%2 KB").arg(fileName).arg(fileSize/1024));
            //连接时设置“选择文件”为不可用,“发送文件”可用
            ui->buttonSend->setEnabled(true);
            ui->buttonSelect->setEnabled(false);
            ui->progressBar->setMaximum(fileSize/1024);
            ui->progressBar->setMinimum(0);
        }
        else
        {
            qDebug()<<"打开文件失败";
        }
    }
    else
    {
        qDebug()<<"文件路径出错";
    }
}

#ifndef UPDATASERVER_H
#define UPDATASERVER_H

#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QList>

namespace Ui {
class UpdataServer;
}

class UpdataServer : public QWidget
{
    Q_OBJECT

public:
    explicit UpdataServer(QWidget *parent = nullptr);
    ~UpdataServer();

private:
    Ui::UpdataServer *ui;

    QTcpServer *tcpServer; //监听套接字
    QList<QTcpSocket*> tcpClientList;//通信套接字
    QTcpSocket *tcpSocket;
    quint16 port;
    QString ip;
    bool FileFlag;
    QString fileName;
    QString fileDir;
    quint32 fileSize;
    quint32 fileLoad;
    QFile file;     //需要接收的文件对象
public slots:

    void NewConnection();
    void disconnectedSlot();
    void ReadyRead();
private slots:
    void on_pushButton_connect_clicked();
};

#endif // UPDATASERVER_H

#include "updataserver.h"
#include "ui_updataserver.h"
#include <string>
#include <QDir>
#include <QCoreApplication>

UpdataServer::UpdataServer(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::UpdataServer)
{
    ui->setupUi(this);

    port = 8888;
    ip = "192.168.1.250";

    tcpSocket = nullptr;
    tcpServer = nullptr;
    tcpServer = new QTcpServer(this);
    QDir dir;
    if(!dir.exists("./Receive"))
    {
        dir.mkpath("./Receive");
    }

    ui->progressBar->setValue(0);

}

UpdataServer::~UpdataServer()
{
    if(tcpServer->isListening()==true)
    {
        if(tcpSocket != nullptr)//判断是否有客户端连接
        {
            for(int i=tcpClientList.length()-1;i>=0;i--)//断开所有连接应从最后开始断开
            {
                //temp =QString("[%1:%2]:退出").arg(tcpClientList.at(i)->peerAddress().toString()).arg(tcpClientList.at(i)->peerPort());
                //ui->textEdit_GetText->append(temp);
                tcpClientList.at(i)->disconnectFromHost();//会触发disconnected信号
                //tcpClientList.removeAt(i);

            }
            if(tcpClientList.isEmpty()==true)
            {
                tcpServer->disconnect();
                tcpServer->close();             //关闭服务器
                tcpServer->deleteLater();
                tcpSocket=nullptr;
            }
        }
    }

    if(file.isOpen()==true)
    {
        file.close();
    }

    delete ui;
}

void UpdataServer::on_pushButton_connect_clicked()
{
    QString temp;
    if(tcpServer->isListening()==true)//服务器正在监听
    {
        if(tcpSocket != nullptr)//判断是否有客户端连接
        {
            for(int i=tcpClientList.length()-1;i>=0;i--)//断开所有连接应从最后开始断开
            {
                //temp =QString("[%1:%2]:退出").arg(tcpClientList.at(i)->peerAddress().toString()).arg(tcpClientList.at(i)->peerPort());
                //ui->textEdit_GetText->append(temp);
                tcpClientList.at(i)->disconnectFromHost();//会触发disconnected信号
                //tcpClientList.removeAt(i);

            }
            if(tcpClientList.isEmpty()==true)
            {
                tcpServer->close();             //关闭服务器
                tcpSocket=nullptr;
                ui->textEdit_GetText->append("停止监听成功");
                ui->pushButton_connect->setText("监听");
                disconnect(tcpServer,&QTcpServer::newConnection,this,&UpdataServer::NewConnection);
            }
        }
        else
        {
            QString str = "当前没有连接,可重新监听";
            tcpServer->close();
            ui->textEdit_GetText->append(str);
            ui->pushButton_connect->setText("监听");
            disconnect(tcpServer,&QTcpServer::newConnection,this,&UpdataServer::NewConnection);
        }
    }
    else
    {
        //if(true == tcpServer->listen(QHostAddress::Any,port))//监听所有Ip
        if(true == tcpServer->listen(QHostAddress(ip),port))
        {
            ui->textEdit_GetText->append("开始监听");
            ui->pushButton_connect->setText("停止");
            FileFlag = false;
            connect(tcpServer,&QTcpServer::newConnection,this,&UpdataServer::NewConnection);
        }
        else
        {
            ui->textEdit_GetText->append("监听失败");
            return ;
        }
    }
}

void UpdataServer::NewConnection()
{
    //取出建立好的套接字
    tcpSocket = tcpServer->nextPendingConnection();
    //获取对方Ip和端口
    QString cip = tcpSocket->peerAddress().toString();
    quint16 prot = tcpSocket->peerPort();
    QString temp= QString("%1.%2:成功连接").arg(cip).arg(prot);
    ui->textEdit_GetText->append(temp);
    //添加到界面以及socket列表中
    temp=temp.split(":")[0];
    tcpClientList.append(tcpSocket);

    connect(tcpSocket,&QTcpSocket::readyRead,this,&UpdataServer::ReadyRead);
    connect(tcpSocket,&QTcpSocket::disconnected,this,&UpdataServer::disconnectedSlot);
}

void UpdataServer::disconnectedSlot()
{
    tcpSocket = static_cast<QTcpSocket *>(this->sender());//得到发出信号的客户端
    QString temp =QString("%1.%2:退出").arg(tcpSocket->peerAddress().toString()).arg(tcpSocket->peerPort());
    ui->textEdit_GetText->append(temp);
    temp=temp.split(":")[0];
    //从链表中删除
    for(int i=0;i<tcpClientList.length();i++)
    {
        if(tcpClientList.at(i)->peerAddress() == tcpSocket->peerAddress())
        {
            if(tcpClientList.at(i)->peerPort() == tcpSocket->peerPort())
            {
                tcpClientList.removeAt(i);
                break;
            }
        }
    }
}

void UpdataServer::ReadyRead()
{
    unsigned char tempStr[4*1024];
    memset(tempStr,0,sizeof(tempStr));
    //获取对方的IP和端口
    //QString cip = tcpSocket->peerAddress().toString();
    //quint16 prot = tcpSocket->peerPort();
    tcpSocket = static_cast<QTcpSocket *>(this->sender());//得到发出信号的客户端
    QByteArray array = tcpSocket->readAll();
    memcpy(tempStr,array.data(),4*1024);

    if(tempStr[0]=='#'&&tempStr[1]=='#'&&tempStr[2]=='#'&&tempStr[7]=='#'&&FileFlag == false)
    {
        fileSize =static_cast<quint32>(tempStr[3]<<24|tempStr[4]<<16|tempStr[5]<<8|tempStr[6]);
        fileLoad = 0;
        fileName = "./Receive/"+QString(reinterpret_cast<char *>(&tempStr[8]));

        ui->progressBar->setMaximum(fileSize/1024);
        ui->progressBar->setMinimum(0);
        file.setFileName(fileName);
        if(!file.open(QIODevice::WriteOnly))
        {
            qDebug()<<"以只写方式打开文件失败";
            tcpSocket->disconnectFromHost();
            return ;
        }
        else
        {
             FileFlag = true;
        }
    }
    else if(FileFlag == true)
    {

        qint64 len = file.write(array);
        //每次写入的大小累加
        if(len > 0)
        {
            fileLoad += len;
        }
        ui->progressBar->setValue(fileLoad/1024);

        if(fileLoad >= fileSize)
        {
            ui->textEdit_GetText->append("文件接收完成");
            fileLoad=0;
            file.close();
            FileFlag = false;
            fileDir = QCoreApplication::applicationDirPath()+QString(fileName).section(".", 1, 2);
            ui->textEdit_GetText->append(QString("FileDir:\n%1\n\nFileSize:%2 KB").arg(fileDir).arg(fileSize/1024));
        }
    }
}

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-07-14 23:16:55  更:2021-07-14 23:17:42 
 
开发: 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/29 9:34:31-

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