<4>[QTCN]图片网络传输工具(服务器端)

简介: 说明:图片网络传输工具(服务器端)。亮点:图片网络传输解码。

@TOC

参考

<7>[QTCN]图片网络传输工具(服务器端)
说明:图片网络传输工具(服务器端)。

亮点:图片网络传输解码。

实现

PictureTcpServer.pro

QT       += network

main.cpp

#include "picturetcpserver.h"
#include <QApplication>
#include <QFont>
int main(int argc, char *argv[])
{
   
   
    QApplication a(argc, argv);
    PictureTcpServer w;
    QFont font;
    font.setPixelSize(25);
    w.setFont(font);
    w.show();
    return a.exec();
}

picturetcpserver.h


#ifndef PICTURETCPSERVER_H
#define PICTURETCPSERVER_H

#include <QWidget>
#include <QtNetwork>
#include <QTcpSocket>
#pragma execution_character_set("utf-8")
QT_BEGIN_NAMESPACE
namespace Ui {
   
    class PictureTcpServer; }
QT_END_NAMESPACE

class PictureTcpServer : public QWidget

{
   
   
    Q_OBJECT

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


    void SaveImage(QByteArray ba);  //保存图片
    void SaveData(QByteArray ba);   //保存数据

    void DelayTime(int ms);
    void ChangeEnable(bool isEnable);
    void StartListen();             //开始监听

private slots:
    void on_btnStart_clicked();

    void on_btnClear_clicked();

    void on_btnSend_clicked();

    void AcceptConnection();        //建立连接
    void ReadMyData();              //接收数据带检验
    void ReceiveData();             //普通方式接收数据
    void DisplayError(QAbstractSocket::SocketError socketError);

    void on_rbtnPT_toggled(bool checked);

private:
    Ui::PictureTcpServer *ui;

    QTcpServer m_tcpServer;
    QTcpSocket *m_pTcpServerConnection;

    QStringList m_fileNames;
    int m_count;                    //统计存放图片的张数

    QByteArray m_message;           //存放从服务器接收到的字符串
    quint16 m_basize;               //存放文件大小信息
};

#endif // PICTURETCPSERVER_H

picturetcpserver.cpp


#include "picturetcpserver.h"
#include "ui_picturetcpserver.h"
#pragma execution_character_set("utf-8")

PictureTcpServer::PictureTcpServer(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::PictureTcpServer)
{
   
   
    ui->setupUi(this);
    ChangeEnable(false);
    this->setWindowIcon(QIcon(":/1.ico"));
    this->setWindowTitle("图片网络传输工具(服务器端)");
    m_count=0;
    m_basize=0;//初始化值0
    connect(&m_tcpServer,SIGNAL(newConnection()),this,SLOT(AcceptConnection()));
}

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

 //接收数据带检验
void PictureTcpServer::ReadMyData()
{
   
   
    this->DelayTime(ui->txtTime->text().toInt());//延时等待数据处理完
    qDebug()<<"ReadMyData()接收数据带检验";
    if(m_pTcpServerConnection==nullptr){
   
   
        qDebug()<<"m_pTcpServerConnection==nullptr";
        return;
    }
    QDataStream in(m_pTcpServerConnection);
    in.setVersion(QDataStream::Qt_4_7);
    if (m_basize==0)
    {
   
   
        //判断接收的数据是否有两字节(文件大小信息)
        //如果有则保存到basize变量中,没有则返回,继续接收数据
        if (m_pTcpServerConnection->bytesAvailable()<(int)sizeof(quint16))
        {
   
   
            return;
        }
        in>>m_basize;
    }

    //如果没有得到全部数据,则返回继续接收数据
    if (m_pTcpServerConnection->bytesAvailable()<m_basize)
    {
   
   
        return;
    }

    /*将只读取剩余的数据部分,而不包括文件大小信息;
     *因为QDataStream类会按照先进先出(FIFO)的顺序读取数据流中的数据。
     *当调用in >> m_basize语句时,它会从数据流中读取指定类型和大小的数据,
     *并将其存储在变量m_basize中。而in >> m_message会继续从数据流中读取剩余的数据*/
    in>>m_message;                      //将接收到的数据存放到变量中

    ui->txtData->append(m_message);
    if (ui->ckbox->isChecked())
    {
   
   
        this->SaveData(m_message);
    }
    this->SaveImage(m_message);
    m_count+=1;
    qDebug()<<"m_count = "<<m_count;
    ui->labCount->setText(QString("提示:数据大小(%1) 图片张数(%2)").arg(QString::number(m_basize),QString::number(m_count)));
    m_basize=0;                         //重新归位0
    m_message.clear();                  //清空后重新存储

}

//保存图片
void PictureTcpServer::SaveImage(QByteArray ba)
{
   
   
    QString timeNow=QDateTime::currentDateTime().toString("yyyyMMddHHmmss");
    QString saveFileName=QCoreApplication::applicationDirPath()+tr("/imageto/%1.jpg").arg(timeNow);

    QDir folder(QCoreApplication::applicationDirPath());
    if (!folder.exists("imageto")) // 检查文件夹是否存在
    {
   
   
        if (!folder.mkpath("imageto")) // 创建文件夹并检查是否成功
        {
   
   
            // 创建文件夹失败,进行适当的错误处理
            return;
        }
    }

    QByteArray rdc=qUncompress(QByteArray::fromBase64(ba));         // 解压缩,得到解压后的二进制数据
    QImage img;
    img.loadFromData(rdc);                  // 从字节数组加载图像数据
    img.save(saveFileName);
}

//保存数据
void PictureTcpServer::SaveData(QByteArray ba)
{
   
   
    QString timeNow=QDateTime::currentDateTime().toString("yyyyMMddHHmmss");
    QString saveFileName=QCoreApplication::applicationDirPath()+tr("/imagedata/%1.txt").arg(timeNow);

    QDir folder(QCoreApplication::applicationDirPath());
    if (!folder.exists("imagedata")) // 检查文件夹是否存在
    {
   
   
        if (!folder.mkpath("imagedata")) // 创建文件夹并检查是否成功
        {
   
   
            // 创建文件夹失败,进行适当的错误处理
            return;
        }
    }

    QString str(ba);
    QFile file(saveFileName);
    if (file.open(QFile::WriteOnly| QIODevice::Truncate))
    {
   
   
        file.write(str.toLatin1());
        file.close();
    }
}

//延时等待功能
void PictureTcpServer::DelayTime(int ms)
{
   
   
    QTime t=QTime::currentTime().addMSecs(ms);//当前时间的基础上增加ms毫秒,得到一个目标时间点t
    while(QTime::currentTime()<t)
    {
   
   /*处理当前线程的事件队列,并等待最多100毫秒来接收新的事件。
      *处理所有类型的事件,包括定时器事件、绘图事件等
      *通过不断处理事件,可以确保程序在等待期间仍然能够响应其他事件,以避免程序无响应或阻塞*/
        QCoreApplication::processEvents(QEventLoop::AllEvents,100);
    }
}

void PictureTcpServer::ChangeEnable(bool isEnable)
{
   
   
    ui->btnStart->setEnabled(!isEnable);
    ui->btnSend->setEnabled(isEnable);
}

//开始监听
void PictureTcpServer::StartListen()
{
   
   
    if (!m_tcpServer.listen(QHostAddress::Any,ui->txtPort->text().toInt()))
    {
   
   
        ui->labCount->setText(tr("提示:发生错误(%1)").arg(m_tcpServer.errorString()));
        m_tcpServer.close();        //关闭TCP服务器,停止接受新的连接请求
        return;
    }
    ui->btnStart->setEnabled(false);
    ui->btnSend->setEnabled(false);
    ui->labCount->setText(tr("提示:正在监听"));
}

//建立连接
void PictureTcpServer::AcceptConnection()
{
   
   
    // 获取TCP服务器对象的下一个待处理的连接
    m_pTcpServerConnection=m_tcpServer.nextPendingConnection();
    connect(m_pTcpServerConnection,&QTcpSocket::readyRead,this,[=](){
   
   
        if (ui->rbtnPT->isChecked())    //普通方式接收数据
        {
   
   
            ReceiveData();
        }
        else                            //数据检验方式接收数据
        {
   
   
            ReadMyData();
        }
    });


    connect(m_pTcpServerConnection,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(DisplayError(QAbstractSocket::SocketError)));

    connect(m_pTcpServerConnection,&QTcpSocket::disconnected,this,[=](){
   
   
        /*为了避免内存泄漏,调用deleteLater()函数以删除不再需要的QAbstractSocket对象;*/
        m_pTcpServerConnection->deleteLater();
        /*deleteLater()函数的作用是在事件循环处理完当前事件后删除对象,这样可以避免直接在槽函数中删除对象导致的问题,
         *而不会立即删除它。*/
    });

    m_tcpServer.close();            //关闭TCP服务器,停止接受新的连接请求
    ui->labCount->setText(tr("提示:客户端连接成功"));
    ui->btnSend->setEnabled(true);
}

//普通方式接收数据
void PictureTcpServer::ReceiveData()
{
   
   
    //this->DelayTime(ui->txtTime->text().toInt());
    QByteArray read=m_pTcpServerConnection->readAll();

    if (!read.isEmpty())
    {
   
   
        ui->txtData->append(QString::fromUtf8(read));
        if (ui->ckbox->isChecked())
        {
   
   
            this->SaveData(read);
        }
    }
}

void PictureTcpServer::DisplayError(QAbstractSocket::SocketError socketError)
{
   
   
    /* 调用close()函数后,QAbstractSocket对象进入QAbstractSocket::UnconnectedState状态,
     * 表示与客户端的连接已经断开,此时对象将无法进行进一步的通信或更新*/
    m_pTcpServerConnection->close();
    ui->labCount->setText(QString("提示:断开连接,错误(%1)").arg(m_pTcpServerConnection->errorString()));
    this->ChangeEnable(false);
}



void PictureTcpServer::on_btnStart_clicked()
{
   
   
    this->StartListen();
}


void PictureTcpServer::on_btnClear_clicked()
{
   
   
    ui->txtData->clear();
}


void PictureTcpServer::on_btnSend_clicked()
{
   
   
    m_pTcpServerConnection->write(ui->txt1->toPlainText().toUtf8());
    if (m_pTcpServerConnection->flush())
    {
   
   
        ui->labCount->setText(tr("提示:发送数据成功"));
    }
}


void PictureTcpServer::on_rbtnPT_toggled(bool checked)
{
   
   
    qDebug()<<"接收方式普通方式 使用="<<checked;
    if(checked)
    {
   
   
        if(m_pTcpServerConnection==nullptr)
            return;
        m_pTcpServerConnection->readAll(); // 读取并丢弃缓冲区中的数据

        qWarning() << "缓冲区已清空";

    }
}

picturetcpserver.ui

image.png

效果

演示.gif

源码

Gitee:05PictureTcpServer[QTCN]图片网络传输工具(服务器端)

模糊知识点

  1. QDataStream类会按照先进先出(FIFO)的顺序读取数据流中的数据
  • 当调用in >> m_basize语句时,它会从数据流中读取指定类型和大小的数据,并将其存储在变量m_basize中。
  • 而in >> m_message会继续从数据流中读取剩余的数据
  1. QTcpServer::close() 关闭TCP服务器,停止接受新的连接请求

  2. QTcpSocket::close() QAbstractSocket对象进入QAbstractSocket::UnconnectedState状态,表示与客户端的连接已经断开,此时对象将 无法 进行进一步的通信或 更新

  3. QTcpSocket::bytesAvailable()函数用于判断是否有足够的字节可供读取,不足则可以继续等待更多数据

//调用bytesAvailable()函数来检查是否已经接收到了完整的数据。
//如果可读取的字节数小于文件大小(m_basize),则返回并继续等待更多数据
if (m_pTcpServerConnection->bytesAvailable()<m_basize)
    return;

通过这个例子可见,当时自己开发的Qt广告机客户端(下位机)QTcpSocket::eadyRead()处理的局限

相关文章
|
3月前
|
Java
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
113 9
|
23天前
|
Linux 网络性能优化 网络安全
Linux(openwrt)下iptables+tc工具实现网络流量限速控制(QoS)
通过以上步骤,您可以在Linux(OpenWrt)系统中使用iptables和tc工具实现网络流量限速控制(QoS)。这种方法灵活且功能强大,可以帮助管理员有效管理网络带宽,确保关键业务的网络性能。希望本文能够为您提供有价值的参考。
76 28
|
1月前
|
数据采集 人工智能 自然语言处理
FireCrawl:开源 AI 网络爬虫工具,自动爬取网站及子页面内容,预处理为结构化数据
FireCrawl 是一款开源的 AI 网络爬虫工具,专为处理动态网页内容、自动爬取网站及子页面而设计,支持多种数据提取和输出格式。
288 19
FireCrawl:开源 AI 网络爬虫工具,自动爬取网站及子页面内容,预处理为结构化数据
|
20天前
|
网络协议 Unix Linux
深入解析:Linux网络配置工具ifconfig与ip命令的全面对比
虽然 `ifconfig`作为一个经典的网络配置工具,简单易用,但其功能已经不能满足现代网络配置的需求。相比之下,`ip`命令不仅功能全面,而且提供了一致且简洁的语法,适用于各种网络配置场景。因此,在实际使用中,推荐逐步过渡到 `ip`命令,以更好地适应现代网络管理需求。
33 11
|
2月前
|
存储 安全 物联网
浅析Kismet:无线网络监测与分析工具
Kismet是一款开源的无线网络监测和入侵检测系统(IDS),支持Wi-Fi、Bluetooth、ZigBee等协议,具备被动监听、实时数据分析、地理定位等功能。广泛应用于安全审计、网络优化和频谱管理。本文介绍其安装配置、基本操作及高级应用技巧,帮助用户掌握这一强大的无线网络安全工具。
95 9
浅析Kismet:无线网络监测与分析工具
|
1月前
|
网络协议 安全 测试技术
Nping工具详解:网络工程师的瑞士军刀
### Nping工具详解:网络工程师的瑞士军刀 Nping是Nmap项目的一部分,支持TCP、UDP、ICMP和ARP等多种协议,用于生成和分析网络数据包。它提供灵活的命令行界面,适用于网络探测、安全测试和故障排除。本文介绍Nping的基础与高级用法,包括发送不同类型的网络请求、自定义TCP标志位、路由跟踪等,并通过实战案例展示其应用。掌握Nping有助于更好地理解和管理网络环境。 (239字符)
80 9
|
2月前
|
运维 监控 Linux
推荐几个不错的 Linux 服务器管理工具
推荐几个不错的 Linux 服务器管理工具
172 6
|
3月前
|
安全 Windows
【Azure Cloud Service】在Windows系统中抓取网络包 ( 不需要另外安全抓包工具)
通常,在生产环境中,为了保证系统环境的安全和纯粹,是不建议安装其它软件或排查工具(如果可以安装,也是需要走审批流程)。 本文将介绍一种,不用安装Wireshark / tcpdump 等工具,使用Windows系统自带的 netsh trace 命令来获取网络包的步骤
103 32
|
2月前
|
缓存 负载均衡 监控
HTTP代理服务器在网络安全中的重要性
随着科技和互联网的发展,HTTP代理IP中的代理服务器在企业业务中扮演重要角色。其主要作用包括:保护用户信息、访问控制、缓存内容、负载均衡、日志记录和协议转换,从而在网络管理、性能优化和安全性方面发挥关键作用。
95 2
|
3月前
|
弹性计算 监控 数据库
制造企业ERP系统迁移至阿里云ECS的实例,详细介绍了从需求分析、数据迁移、应用部署、网络配置到性能优化的全过程
本文通过一个制造企业ERP系统迁移至阿里云ECS的实例,详细介绍了从需求分析、数据迁移、应用部署、网络配置到性能优化的全过程,展示了企业级应用上云的实践方法与显著优势,包括弹性计算资源、高可靠性、数据安全及降低维护成本等,为企业数字化转型提供参考。
88 5

热门文章

最新文章