TCP通信(02)

13 篇文章 0 订阅
6 篇文章 0 订阅

客户端向服务端发送数据

客户端

#include "server.h"
#include "ui_server.h"
#include <QtNetwork>

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

    connect(&tcpServer, SIGNAL(newConnection()),
            this, SLOT(acceptConnection()));

}

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

void Server::start()
{
    if (!tcpServer.listen(QHostAddress::LocalHost, 6666)) {
        qDebug() << tcpServer.errorString();
        close();
        return;
    }
    ui->startButton->setEnabled(false);
    totalBytes = 0;
    bytesReceived = 0;
    fileNameSize = 0;
    ui->serverStatusLabel->setText(tr("监听"));
    ui->serverProgressBar->reset();
}

void Server::acceptConnection()
{
    tcpServerConnection = tcpServer.nextPendingConnection();
    connect(tcpServerConnection, SIGNAL(readyRead()),
            this, SLOT(updateServerProgress()));
    connect(tcpServerConnection, SIGNAL(error(QAbstractSocket::SocketError)),
            this, SLOT(displayError(QAbstractSocket::SocketError)));
    ui->serverStatusLabel->setText(tr("接受连接"));
    // 关闭服务器,不再进行监听
    tcpServer.close();
}


void Server::updateServerProgress()
{
    QDataStream in(tcpServerConnection);
    in.setVersion(QDataStream::Qt_5_6);

    // 如果接收到的数据小于16个字节,保存到来的文件头结构
    if (bytesReceived <= sizeof(qint64)*2) {
        if((tcpServerConnection->bytesAvailable() >= sizeof(qint64)*2)
                && (fileNameSize == 0)) {
            // 接收数据总大小信息和文件名大小信息
            in >> totalBytes >> fileNameSize;
            bytesReceived += sizeof(qint64) * 2;
        }
        if((tcpServerConnection->bytesAvailable() >= fileNameSize)
                && (fileNameSize != 0)) {
            // 接收文件名,并建立文件
            in >> fileName;
            ui->serverStatusLabel->setText(tr("接收文件 %1 …")
                                           .arg(fileName));
            bytesReceived += fileNameSize;
            localFile = new QFile(fileName);
            if (!localFile->open(QFile::WriteOnly)) {
                qDebug() << "server: open file error!";
                return;
            }
        } else {
            return;
        }
    }
    // 如果接收的数据小于总数据,那么写入文件
    if (bytesReceived < totalBytes) {
        bytesReceived += tcpServerConnection->bytesAvailable();
        inBlock = tcpServerConnection->readAll();
        localFile->write(inBlock);
        inBlock.resize(0);
    }
    ui->serverProgressBar->setMaximum(totalBytes);
    ui->serverProgressBar->setValue(bytesReceived);

    // 接收数据完成时
    if (bytesReceived == totalBytes) {
        tcpServerConnection->close();
        localFile->close();
        ui->startButton->setEnabled(true);
        ui->serverStatusLabel->setText(tr("接收文件 %1 成功!")
                                       .arg(fileName));
    }
}

void Server::displayError(QAbstractSocket::SocketError socketError)
{
    qDebug() << tcpServerConnection->errorString();
    tcpServerConnection->close();
    ui->serverProgressBar->reset();
    ui->serverStatusLabel->setText(tr("服务端就绪"));
    ui->startButton->setEnabled(true);
}

// 开始监听按钮
void Server::on_startButton_clicked()
{
    start();
}
#include "tcpclientdialog.h"
#include "ui_tcpclientdialog.h"

#include <QFileDialog>

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

    payloadSize = 64 * 1024;
    totalBytes = 0;
    bytesWritten = 0;
    bytesToWrite = 0;
    tcpClient = new QTcpSocket(this);
    connect(tcpClient, SIGNAL(connected()),
            this, SLOT(startTransfer()));
    connect(tcpClient, SIGNAL(bytesWritten(qint64)),
            this, SLOT(updateClientProgress(qint64)));
    connect(tcpClient, &QAbstractSocket::errorOccurred,
            this, &TcpClientDialog::displayError);

    ui->sendPushButton->setEnabled(false);
}

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

void TcpClientDialog::openFile()
{
    fileName = QFileDialog::getOpenFileName(this);
    if(!fileName.isEmpty()){
        ui->sendPushButton->setEnabled(true);
        ui->messageLabel->setText(tr("打开文件 %1 成功!").arg(fileName));
    }
}

void TcpClientDialog::send()
{
    ui->sendPushButton->setEnabled(false);
    bytesWritten = 0;
    ui->messageLabel->setText(tr("连接中……"));
    tcpClient->connectToHost(ui->hostLineEdit->text(),
                             ui->portLineEdit->text().toInt());

}

void TcpClientDialog::startTransfer()
{
    localFile = new QFile(fileName);
    if(!localFile->open(QFile::ReadOnly))
    {
        qDebug() << tr("客户端:打开文件失败!");
        return;
    }
    totalBytes = localFile->size();
    QDataStream sendOut(&outBlock, QIODevice::WriteOnly);
    sendOut.setVersion(QDataStream::Qt_5_9);
    QString currentFileName = fileName.right(
                fileName.size() - fileName.lastIndexOf("/") - 1);
    qDebug() << "fileName" << fileName;
            // << (fileName.lastIndexOf("/")) << std::endl
            // << (fileName.size() - fileName.lastIndexOf("/") - 1);

    //总大小信息空间、文件名大小信息空间、文件名。
    sendOut << qint64(0) << qint64(0) << currentFileName;

    totalBytes += outBlock.size();
    sendOut.device()->seek(0);

    sendOut << totalBytes << qint64(outBlock.size() - sizeof(qint64)*2);
    //发送完文件头结构后剩余数据的大小。
    bytesToWrite = totalBytes - tcpClient->write(outBlock);
    ui->messageLabel->setText(tr("已连接"));
    outBlock.resize(0);


}

void TcpClientDialog::updateClientProgress(qint64 numBytes)
{
    bytesWritten += (int)numBytes;
    if(bytesToWrite > 0){
        //每次发送payloadSize大小的数据,不足发送剩余大小的数据;
        outBlock = localFile->read(qMin(bytesToWrite, payloadSize));
        bytesToWrite -= (int)tcpClient->write(outBlock);
        outBlock.resize(0);
    }else{
        localFile->close();
    }
    ui->clientProgressBar->setMaximum(totalBytes);
    ui->clientProgressBar->setValue(bytesWritten);
    if(bytesWritten == totalBytes){
        ui->messageLabel->setText(tr("传输文件 %1 成功!").arg(fileName));
        localFile->close();
        tcpClient->close();
    }


}


void TcpClientDialog::displayError(QAbstractSocket::SocketError socketError)
{
    qDebug() << tcpClient->errorString();
    tcpClient->close();
    ui->clientProgressBar->reset();
    ui->messageLabel->setText(tr("客户端就绪!"));
    ui->sendPushButton->setEnabled(true);

}



void TcpClientDialog::on_openPushButton_clicked()
{
    ui->clientProgressBar->reset();
    ui->messageLabel->setText(tr("状态:等待打开文件!"));
    openFile();
}


void TcpClientDialog::on_sendPushButton_clicked()
{
    send();
}

服务端

#ifndef TCPSERVERDIALOG_H
#define TCPSERVERDIALOG_H

#include <QDialog>
#include <QAbstractSocket>
#include <QtNetwork>
#include <QDebug>

class QTcpSocket;
class QFile;

QT_BEGIN_NAMESPACE
namespace Ui { class TcpServerDialog; }
QT_END_NAMESPACE

class TcpServerDialog : public QDialog
{
    Q_OBJECT

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

private slots:
    void start();
    void acceptConnection();
    void updateServerProgress();
    void displayError(QAbstractSocket::SocketError socketError);
    void on_pushButton_clicked();

private:
    Ui::TcpServerDialog *ui;
    QTcpServer tcpServer;
    QTcpSocket *tcpServerConnection;
    qint64 totalBytes;
    qint64 bytesReceived;
    qint64 fileNameSize;
    QString fileName;
    QFile *localFile;
    QByteArray inBlock;//缓冲区
};
#endif // TCPSERVERDIALOG_H

#include "tcpserverdialog.h"
#include "ui_tcpserverdialog.h"


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

    connect(&tcpServer, SIGNAL(newConnection()),
            this, SLOT(acceptConnection()));

}

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

void TcpServerDialog::start()
{
    //QHostAddress::LocalHost 等价于QHostAddress("127.0.0.1")
    if(!tcpServer.listen(QHostAddress::LocalHost, 6666)){
        qDebug() << tcpServer.errorString();
        close();
        return;
    }
    ui->pushButton->setEnabled(false);
    totalBytes = 0;
    bytesReceived = 0;
    fileNameSize = 0;
    ui->messageLabel->setText(tr("监听!"));
    ui->progressBar->reset();
}

void TcpServerDialog::acceptConnection()
{
    tcpServerConnection = tcpServer.nextPendingConnection();
    connect(tcpServerConnection, &QTcpSocket::readyRead,
            this, &TcpServerDialog::updateServerProgress);
    connect(tcpServerConnection, &QAbstractSocket::errorOccurred,
            this, &TcpServerDialog::displayError);
    ui->messageLabel->setText(tr("接受连接"));
    // 关闭服务器,不再进行监听
    tcpServer.close();

}

void TcpServerDialog::updateServerProgress()
{
    QDataStream in(tcpServerConnection);
    in.setVersion(QDataStream::Qt_5_9);
    if(bytesReceived <= sizeof(qint64)*2){
        if((tcpServerConnection->bytesAvailable() >= sizeof(qint64)*2)
                && (fileNameSize == 0)){
            in >> totalBytes >> fileNameSize;
        bytesReceived += sizeof(qint64) * 2;
        }
        if((tcpServerConnection->bytesAvailable() >= fileNameSize)
            && (fileNameSize != 0)){
            in >> fileName;
            ui->messageLabel->setText(tr("接收文件 %1 ……").arg(fileName));
            bytesReceived += fileNameSize;
            localFile = new QFile(fileName);
            if(!localFile->open(QFile::WriteOnly)){
                qDebug() << "服务端:打开文件失败!";
                return;
            }
        }else{
            return;
        }

    }

    if(bytesReceived <totalBytes){
        bytesReceived += tcpServerConnection->bytesAvailable();
        inBlock = tcpServerConnection->readAll();
        localFile->write(inBlock);
        inBlock.resize(0);

    }
    ui->progressBar->setMaximum(totalBytes);
    ui->progressBar->setValue(bytesReceived);
    if(bytesReceived == totalBytes){
        tcpServerConnection->close();
        localFile->close();
        ui->pushButton->setEnabled(true);
        ui->messageLabel->setText(tr("接收文件 %1 成功!").arg(fileName));
    }

}

void TcpServerDialog::displayError(QAbstractSocket::SocketError socketError)
{
    qDebug() << tcpServerConnection->errorString();
    tcpServerConnection->close();
    ui->progressBar->reset();
    ui->messageLabel->setText(tr("服务端就绪!"));
    ui->pushButton->setEnabled(true);

}


void TcpServerDialog::on_pushButton_clicked()
{
    start();
}

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值