QT的TCP通信

原理:

效果图:

代码:

1.服务器端的.h文件

#ifndef SERVERWIDGET_H
#define SERVERWIDGET_H

#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTimer>
#include <QFile>


QT_BEGIN_NAMESPACE
namespace Ui { class serverWidget; }
QT_END_NAMESPACE

class serverWidget : public QWidget
{
    Q_OBJECT

public:
    serverWidget(QWidget *parent = nullptr);
    ~serverWidget();

    void sendData();

private:
    Ui::serverWidget *ui;

    QTcpServer *tcpServer;
    QTcpSocket *tcpSocket;
    QTimer *timer;
    QString fileName;
    quint16 fileSize;
    QFile file;
};
#endif // SERVERWIDGET_H

2.服务器端的.cpp文件

#include "serverwidget.h"
#include "ui_serverwidget.h"

#include <QHostAddress>
#include <QFile>
#include <QFileInfo>
#include <QFileDialog>

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

    tcpServer = new QTcpServer(this);
    tcpServer->listen(QHostAddress::Any,8888);
    setWindowTitle("服务器端口:8888");

    ui->pushButtonOpen->setEnabled(false);
    ui->pushButtonSend->setEnabled(false);

    connect(tcpServer,&QTcpServer::newConnection,[=](){
        tcpSocket = tcpServer->nextPendingConnection();
        if(tcpSocket != NULL){
            QString ip = tcpSocket->peerName();
            quint16 port = tcpSocket->peerPort();
            ui->textEdit->setText(QString("客户端:%1  socket:%2").arg(ip).arg(port));

            ui->pushButtonOpen->setEnabled(true);
        }

        connect(tcpSocket,&QTcpSocket::readyRead,[=](){
            QByteArray buf = tcpSocket->readAll();
            ui->textEdit->append(buf);
        });
    });

    timer = new QTimer;
    timer->setSingleShot(true);
    connect(timer,&QTimer::timeout,[=](){
        sendData();
    });

    connect(ui->pushButtonOpen,&QPushButton::clicked,[=](){
        QString filePath = QFileDialog::getOpenFileName(this,"打开文件","../");
        QFileInfo info(filePath);
        fileName = info.fileName();
        fileSize = info.size();
        file.setFileName(filePath);
        bool isOpen = file.open(QIODevice::ReadOnly);
        if(isOpen == false){
            qDebug("源文件打开失败");
            return ;
        }
        ui->textEdit->append(QString("%1 该文件已选中").arg(filePath));
        ui->pushButtonSend->setEnabled(true);
        ui->pushButtonOpen->setEnabled(false);
    });

    connect(ui->pushButtonSend,&QPushButton::clicked,[=](){
        //先写文件信息
        qint64 len = tcpSocket->write(QString(fileName+"##"+QString::number(fileSize)).toLatin1().data());
        if(len > 0){
            timer->start(100);
        }
    });



}

serverWidget::~serverWidget()
{
    delete ui;
}

void serverWidget::sendData()
{
    ui->textEdit->append("开始传送文件。。。。。");
    char buf[4*1024]={0};
    qint64 readLen = 0;
    qint64 writeLen = 0;
    qint64 totalLen = 0;

    while((readLen = file.read(buf,sizeof (buf))) > 0){

        writeLen = tcpSocket->write(buf,readLen);
        totalLen += writeLen;
        qDebug()<<"readLen="+QString::number(readLen);
    }

    if(totalLen == fileSize){
        ui->textEdit->append("服务器文件发送完毕。。。。");
    }else{
        ui->textEdit->append("服务器文件发送失败xxxxxx");
    }
}

3.客户端的.h文件

#ifndef CLIENTWIDGET_H
#define CLIENTWIDGET_H

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

namespace Ui {
class clientWidget;
}

class clientWidget : public QWidget
{
    Q_OBJECT

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

private:
    Ui::clientWidget *ui;

    QTcpSocket *tcpSocket;
    bool isStart;
    QFile file;
    qint16 recvSize;
    qint16 fileSize;

};

#endif // CLIENTWIDGET_H

4.客户端的.cpp文件

#include "clientwidget.h"
#include "ui_clientwidget.h"

#include <QHostAddress>

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

    tcpSocket = new QTcpSocket(this);
    setWindowTitle("客户端");
    isStart = false;
    recvSize = 0;

    connect(ui->connectBtn,&QPushButton::clicked,[=](){
        tcpSocket->connectToHost(ui->lineEditIP->text(),ui->lineEditPort->text().toUInt());
        connect(tcpSocket,&QTcpSocket::readyRead,[=](){
            QByteArray buf = tcpSocket->readAll();
            if(isStart == false){
                isStart = true;
                QString fileName = QString(buf).section("##",0,0);
                fileSize = QString(buf).section("##",1,1).toInt();
                //file = new QFile(QString("C:/Users/Administrator/Desktop/%1").arg(fileName));
                file.setFileName(QString("C:/Users/Administrator/Desktop/%1").arg(fileName));
                bool isOpen = file.open(QIODevice::WriteOnly);
                if(isOpen){
                    ui->progressBar->setValue(0);
                    ui->progressBar->setMinimum(0);
                    ui->progressBar->setMaximum(fileSize/1024);
                }else{
                    file.close();
                }
            }else{
                qint16 len = file.write(buf);
                recvSize += len;
                ui->progressBar->setValue(recvSize/1024);
                if(recvSize == fileSize){
                    tcpSocket->write("file done");
                    file.close();
                }
            }
        });
    });

    connect(ui->disconnectBtn,&QPushButton::clicked,[=](){
        tcpSocket->write(QString("%1:%2 disconnect").arg(tcpSocket->localAddress().toString()).arg(tcpSocket->localPort()).toLatin1().data());
        tcpSocket->disconnectFromHost();
        tcpSocket->close();
    });
}

clientWidget::~clientWidget()
{
    delete ui;
}

心得:

1.程序异常导致终端错误:【原因1:定义的指针没有new】

2.QFIleDialog | QFileInfo | QFile 等,可以直接使用它的静态公用成员【Static Public Members】。

3.file.close()  与  delete

猜你喜欢

转载自blog.csdn.net/weixin_42470290/article/details/114363711
今日推荐