基于Qt的UDP通信、TCP文件传输程序的设计与实现——QQ聊天群聊

🙌秋名山码民的主页
😂oi退役选手,Java、大数据、单片机、IoT均有所涉猎,热爱技术,技术无罪
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
获取源码,添加WX

目录

  • 前言
  • 一、主界面和聊天窗口
  • 二、UDP聊天
  • 三、TCP文件传输
    • server类
    • Clint类
  • 最后


前言

QQ是一款优秀的聊天软件,本文将提供主要代码和思路来实现一个类似于QQ群聊的网络聊天软件,大致有以下俩个功能:

采用qt5编写,实现基于UDP的文本聊天功能,和基于TCP的文件传输功能

基本聊天会话功能

通过获取每一个用户运行该程序的时候,发送广播来实现,不仅用户登录的时候进行广播,退出、发送信息的时候都使用UDP广播来告知用户,每个用户的聊天窗口为一个端点

文件传输功能实现

文件的传输采用TCP来实现,用C/S架构

  1. 主界面选中要发送的文件,单击传输,打开发送文件对话框
  2. 当用户单击发送的时候,程序通过UDP广播给接收端,接收端在收到文件的UDP消息后,弹出提示框,是否接收
  3. 如果接收,先创建一个TCP通信客户端,双方进行TCP通信,如果拒绝,再通过UDP广播告知发送端

一、主界面和聊天窗口

在这里插入图片描述

#ifndef DRAWER_H
#define DRAWER_H

#include <QToolBox>
#include <QToolButton>
#include <QWidget>
#include "myqq.h"

class Drawer : public QToolBox
{
public:
    Drawer();
private:
    QToolButton *toolBtn1;


    //聊天对象窗口指针
    QWidget *chatWidget1;



private slots:
    // 显示聊天对象窗口
    void showChatWidget1();


    MyQQ *myqq;

};

#endif // DRAWER_H
 	setWindowTitle(tr("My QQ v01"));
    setWindowIcon(QPixmap(":/images/R-C.jpg"));

    toolBtn1 = new QToolButton;
    toolBtn1->setText(tr("冰雪奇缘"));
    toolBtn1->setIcon(QPixmap(":/images/girl1.jpg"));
    toolBtn1->setAutoRaise(true); //设置toolBtn1在显示时自动提升,使得按钮外观更加立体感。
    toolBtn1->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); //设置toolBtn1的按钮样式为图标在文本旁边的形式。
    // 将显示函数与抽屉盒中相对应的用户按钮进行绑定
    //connect(toolBtn1,SIGNAL(clicked()),this,SLOT(showChatWidget1()));
    //connect(toolBtn1, &QToolButton::clicked, this, &QToolBox::showChatWidget1);
    connect(toolBtn1, &QToolButton::clicked, this, &Drawer::showChatWidget1);

二、UDP聊天

原理:如果要进行聊天,则首先要获取所有登录用户的信息,这个功能是通过在每一个用户运行该程序时发送广播实现的,不仅用户登录时要进行广播,而且在用户退出、发送消息时都使用UDP广播来告知所有用户。

#ifndef SERVER_H
#define SERVER_H

#include <QDialog>
#include <QFile>
#include <QTcpServer>
#include <QTime>

namespace Ui {
class Server;
}

class Server : public QDialog
{
    Q_OBJECT

public:
    explicit Server(QWidget *parent = nullptr);
    ~Server();
    void initSrv(); // 初始化服务器
    void refused(); // 关闭服务器

protected:
    void closeEvent(QCloseEvent *);
    void updClntProgress(qint64 numBytes);

private slots:
    void on_Server_accepted();
    void sendMsg(); //发送数据
    void updclntProgress(qint64 numBytes); // 更新进度条

    void on_sOpenBtn_clicked();

    void on_sSendBtn_clicked();

    void on_sCloseBtn_clicked();

private:
    Ui::Server *ui;
    qint16 tPort;
    QTcpServer *tSrv;
    QString fileName;
    QString theFileName;
    QFile *locFile; //待发送的文件
    qint64 totalBytes; //总共要发送的
    qint64 bytesWritten; //已发送的
    qint64 bytesTobeWrite; //待发送的
    qint64 payloadSize;  //被初始化为一个常量
    QByteArray outBlock; // 缓存一次的
    QTcpSocket *clntConn;
    QTime time;

signals:
    void sendFileName(QString fileName);
};

#endif // SERVER_H

#include "server.h"
#include "ui_server.h"

#include <QFile>
#include<QTcpServer>
#include<QTcpSocket>
#include<QMessageBox>
#include <QFileDialog>
#include<QDebug>

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

    setFixedSize(400,207);
    tPort = 5555;
    tSrv = new QTcpServer(this);
    connect(tSrv,&QTcpServer::newConnection,this,&Server::sendMsg);
    initSrv();
}

void Server::initSrv()
{
    payloadSize = 64*1024;
    totalBytes = 0;
    bytesWritten = 0;

    ui->sOpenBtn->setEnabled(true);
    ui->sSendBtn->setEnabled(false);
    tSrv->close();
}

// 发送数据
void Server::sendMsg()
{
    ui->sSendBtn->setEnabled(false);
    clntConn = tSrv->nextPendingConnection();
    connect(clntConn,SIGNAL(bytesWritten(gint64)),this,SLOT(updCIntProgress(qint64)));
    ui->sStatusLabel->setText(tr("开始传送文件 号1 !").arg(theFileName));
    locFile = new QFile(fileName);
    if(!locFile->open((QFile::ReadOnly)))
    {
        QMessageBox::warning(this,tr("应用程序"), tr("无法读取文件号1: n各2").arg(fileName).arg(locFile->errorString()));
        return;
    }
    totalBytes = locFile->size();
    QDataStream sendOut(&outBlock, QIODevice::WriteOnly);

    sendOut.setVersion(QDataStream::Qt_4_7);
    time.start();
    QString curFile = fileName.right(fileName.size() - fileName.lastIndexOf('/') - 1);
    sendOut << qint64(0) << qint64((outBlock.size() - sizeof(qint64)*2));

    bytesTobeWrite = totalBytes - clntConn->write(outBlock);
    outBlock.reserve(0);
}

// 更新进度条
void Server::updClntProgress(qint64 numBytes)
{
    // 防止传输大文件产生冻结
    qApp->processEvents();
    bytesWritten += (int)numBytes;
    if(bytesTobeWrite > 0)
    {
        outBlock = locFile->read(qMin(bytesTobeWrite,payloadSize));
        bytesTobeWrite -= (int)clntConn->write(outBlock);
        outBlock.resize(0);
    } else{
        locFile->close();
    }
    ui->progressBar->setMaximum(totalBytes);
    ui->progressBar->setValue(bytesWritten);
    float useTime = time.elapsed();
    double speed = bytesWritten / useTime;
    ui->sStatusLabel->setText(tr("已发送 %1MB (%2MB/s)\n 共%3MB 已用时:%4s\n 估计剩余时间:%5秒")
            .arg(bytesWritten/(1024*1024))
            .arg(bytesWritten / (1024*1024))
            .arg(speed*1000 / (1024*1024),0,'f',0)
            .arg(totalBytes / (1024 * 1024)).arg(useTime/1000,0,'f',0)
            .arg(totalBytes/speed/1000 - useTime/1000,0,'f',0));
    if(bytesWritten == totalBytes)
    {
            locFile->close();
            tSrv->close();
            ui->sStatusLabel->setText(tr("传送文件 %1 成功").arg(theFileName));
    }

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



void Server::on_sOpenBtn_clicked()
{
    fileName = QFileDialog::getOpenFileName(this);

    if(!fileName.isEmpty())
    {
        theFileName = fileName.right(fileName.size() - fileName.lastIndexOf('/')-1);
        ui->sStatusLabel->setText(tr("要发送的文件为:%1").arg(theFileName));
        ui->sOpenBtn->setEnabled(false);
        ui->sSendBtn->setEnabled(true);
    }
}


void Server::on_sSendBtn_clicked()
{
    if(!tSrv->listen(QHostAddress::Any,tPort))
    {
        qDebug() << tSrv ->errorString();
        close();
        return;
    }
    ui->sStatusLabel->setText("等待……");
    emit sendFileName(theFileName);
}


void Server::on_sCloseBtn_clicked()
{
   if(tSrv->isListening())
   {
       tSrv->close();
       if(locFile->isOpen())
           locFile->close();
       clntConn->abort();
   }
   close();
}

void Server::closeEvent(QCloseEvent *)
{
    on_sCloseBtn_clicked();
}

void Server::refused()
{
    tSrv->close();
    ui->sStatusLabel->setText(tr("对方拒绝!"));
}

三、TCP文件传输

文件的传输采用TCP来实现,用C/S(客户端/服务器)方式,创建俩个新类,client和server类

server类

在这里插入图片描述

#ifndef SERVER_H
#define SERVER_H

#include <QDialog>
#include <QFile>
#include <QTcpServer>
#include <QTime>

namespace Ui {
class Server;
}

class Server : public QDialog
{
    Q_OBJECT

public:
    explicit Server(QWidget *parent = nullptr);
    ~Server();
    void initSrv(); // 初始化服务器
    void refused(); // 关闭服务器

protected:
    void closeEvent(QCloseEvent *);
    void updClntProgress(qint64 numBytes);

private slots:
    void on_Server_accepted();
    void sendMsg(); //发送数据
    void updclntProgress(qint64 numBytes); // 更新进度条

    void on_sOpenBtn_clicked();

    void on_sSendBtn_clicked();

    void on_sCloseBtn_clicked();

private:
    Ui::Server *ui;
    qint16 tPort;
    QTcpServer *tSrv;
    QString fileName;
    QString theFileName;
    QFile *locFile; //待发送的文件
    qint64 totalBytes; //总共要发送的
    qint64 bytesWritten; //已发送的
    qint64 bytesTobeWrite; //待发送的
    qint64 payloadSize;  //被初始化为一个常量
    QByteArray outBlock; // 缓存一次的
    QTcpSocket *clntConn;
    QTime time;

signals:
    void sendFileName(QString fileName);
};

#endif // SERVER_H

#include "server.h"
#include "ui_server.h"

#include <QFile>
#include<QTcpServer>
#include<QTcpSocket>
#include<QMessageBox>
#include <QFileDialog>
#include<QDebug>

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

    setFixedSize(400,207);
    tPort = 5555;
    tSrv = new QTcpServer(this);
    connect(tSrv,&QTcpServer::newConnection,this,&Server::sendMsg);
    initSrv();
}

void Server::initSrv()
{
    payloadSize = 64*1024;
    totalBytes = 0;
    bytesWritten = 0;

    ui->sOpenBtn->setEnabled(true);
    ui->sSendBtn->setEnabled(false);
    tSrv->close();
}

// 发送数据
void Server::sendMsg()
{
    ui->sSendBtn->setEnabled(false);
    clntConn = tSrv->nextPendingConnection();
    connect(clntConn,SIGNAL(bytesWritten(gint64)),this,SLOT(updCIntProgress(qint64)));
    ui->sStatusLabel->setText(tr("开始传送文件 号1 !").arg(theFileName));
    locFile = new QFile(fileName);
    if(!locFile->open((QFile::ReadOnly)))
    {
        QMessageBox::warning(this,tr("应用程序"), tr("无法读取文件号1: n各2").arg(fileName).arg(locFile->errorString()));
        return;
    }
    totalBytes = locFile->size();
    QDataStream sendOut(&outBlock, QIODevice::WriteOnly);

    sendOut.setVersion(QDataStream::Qt_4_7);
    time.start();
    QString curFile = fileName.right(fileName.size() - fileName.lastIndexOf('/') - 1);
    sendOut << qint64(0) << qint64((outBlock.size() - sizeof(qint64)*2));

    bytesTobeWrite = totalBytes - clntConn->write(outBlock);
    outBlock.reserve(0);
}

// 更新进度条
void Server::updClntProgress(qint64 numBytes)
{
    // 防止传输大文件产生冻结
    qApp->processEvents();
    bytesWritten += (int)numBytes;
    if(bytesTobeWrite > 0)
    {
        outBlock = locFile->read(qMin(bytesTobeWrite,payloadSize));
        bytesTobeWrite -= (int)clntConn->write(outBlock);
        outBlock.resize(0);
    } else{
        locFile->close();
    }
    ui->progressBar->setMaximum(totalBytes);
    ui->progressBar->setValue(bytesWritten);
    float useTime = time.elapsed();
    double speed = bytesWritten / useTime;
    ui->sStatusLabel->setText(tr("已发送 %1MB (%2MB/s)\n 共%3MB 已用时:%4s\n 估计剩余时间:%5秒")
            .arg(bytesWritten/(1024*1024))
            .arg(bytesWritten / (1024*1024))
            .arg(speed*1000 / (1024*1024),0,'f',0)
            .arg(totalBytes / (1024 * 1024)).arg(useTime/1000,0,'f',0)
            .arg(totalBytes/speed/1000 - useTime/1000,0,'f',0));
    if(bytesWritten == totalBytes)
    {
            locFile->close();
            tSrv->close();
            ui->sStatusLabel->setText(tr("传送文件 %1 成功").arg(theFileName));
    }

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



void Server::on_sOpenBtn_clicked()
{
    fileName = QFileDialog::getOpenFileName(this);

    if(!fileName.isEmpty())
    {
        theFileName = fileName.right(fileName.size() - fileName.lastIndexOf('/')-1);
        ui->sStatusLabel->setText(tr("要发送的文件为:%1").arg(theFileName));
        ui->sOpenBtn->setEnabled(false);
        ui->sSendBtn->setEnabled(true);
    }
}


void Server::on_sSendBtn_clicked()
{
    if(!tSrv->listen(QHostAddress::Any,tPort))
    {
        qDebug() << tSrv ->errorString();
        close();
        return;
    }
    ui->sStatusLabel->setText("等待……");
    emit sendFileName(theFileName);
}


void Server::on_sCloseBtn_clicked()
{
   if(tSrv->isListening())
   {
       tSrv->close();
       if(locFile->isOpen())
           locFile->close();
       clntConn->abort();
   }
   close();
}

void Server::closeEvent(QCloseEvent *)
{
    on_sCloseBtn_clicked();
}

void Server::refused()
{
    tSrv->close();
    ui->sStatusLabel->setText(tr("对方拒绝!"));
}

Clint类

TCP客户端类,用于接收文件。
在这里插入图片描述

#ifndef CLIENT_H
#define CLIENT_H

#include <QDialog>
#include <QHostAddress>
#include <QFile>
#include <QTime>
#include <QTcpSocket>


namespace Ui {
class client;
}

class client : public QDialog
{
    Q_OBJECT

public:
    explicit client(QWidget *parent = nullptr);
    ~client();
    void setHostAddr(QHostAddress addr);
    void setFileName(QString name);

protected:
    void closeEvent(QCloseEvent *);


private:
    Ui::client *ui;
    QTcpSocket *tClnt;
    quint16 blockSize;
    QHostAddress hostAddr;
    qint16 tPort;
    qint64 totalBytes;
    qint64 bytesReceived;
    qint64 fileNameSize;
    QString fileName;
    QFile *locFile;
    QByteArray inBlock;
    QTime time;

private slots:
    void newConn(); // 连接到服务器
    void readMsg(); // 读取文件数据
//    void displayErr(QAbstractSocket::SocketError); // 显示错误信息
    void on_cCancleBtn_clicked();
    void on_cCloseBtn_clicked();
};

#endif // CLIENT_H

#include "client.h"
#include "ui_client.h"
#include <QDebug>
#include <QMessageBox>
#include <QTime>

client::client(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::client)
{
    ui->setupUi(this);
    setFixedSize(400,190);
    totalBytes = 0;
    bytesReceived = 0;
    fileNameSize = 0;
    tClnt = new QTcpSocket(this);
    tPort = 5555;
    connect(tClnt, &QTcpSocket::readyRead, this, &client::readMsg);


}


// 连接服务器
void client::newConn()
{
    blockSize = 0;
    tClnt->abort();
    tClnt->connectToHost(hostAddr,tPort);
    time.start();
}

// 发送文件
void client::readMsg()
{
    QDataStream in(tClnt);
    in.setVersion(QDataStream::Qt_4_7);
    float useTime = time.elapsed();
    if (bytesReceived <= sizeof(qint64)*2)
    {
        if ((tClnt->bytesAvailable() >= sizeof(qint64)*2) && (fileNameSize == 0))
        {
            in>>totalBytes>>fileNameSize;
            bytesReceived += sizeof(qint64)*2;
        }
        if((tClnt->bytesAvailable() >= fileNameSize) && (fileNameSize != 0))
        {
            in>>fileName;
            bytesReceived +=fileNameSize;
            if(!locFile->open(QFile::WriteOnly))
            {
                QMessageBox::warning(this,tr("应用程序"),tr("无法读取文件%1:\n%2.").arg(fileName).arg(locFile->errorString()));
            }
            return;
        }else
        {
            return;
        }
    }
    if (bytesReceived < totalBytes)
    {
        bytesReceived += tClnt->bytesAvailable();
        inBlock = tClnt->readAll();
        locFile->write(inBlock);
        inBlock.resize(0);
    }
    ui->progressBar->setMaximum(totalBytes);
    ui->progressBar->setValue(bytesReceived);
    double speed = bytesReceived / useTime;
    ui->label_2->setText(tr("已接收 %1MB (%2MB/s)\n 共%3MB 已用时:%4s\n 估计剩余时间:%5秒")
                         .arg(bytesReceived/(1024*1024))
                         .arg(speed*1000 / (1024*1024),0,'f',0)
                         .arg(totalBytes / (1024 * 1024))
                         .arg(useTime/1000,0,'f',0)
                         .arg(totalBytes/speed/1000 - useTime/1000,0,'f',0));
     if(bytesReceived == totalBytes)
     {
         locFile->close();
         tClnt->close();
         ui->label->setText(tr("接收文件 %1 成功").arg(fileName));
     }
}
client::~client()
{
    delete ui;
}

void client::on_cCancleBtn_clicked()
{
    tClnt->abort();
    if(locFile->isOpen())
        locFile->close();

}


void client::on_cCloseBtn_clicked()
{
    tClnt->abort();
    if(locFile->isOpen())
        locFile->close();
    close();
}

void client::closeEvent(QCloseEvent *)
{
    on_cCloseBtn_clicked();
}

最后

至此已完成,读者还可根据自己所需来添加一些拓展功能,更改字体、字号和颜色等等……如果本文对你有所帮助,还请三连支持一下博主!
请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/177874.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

词向量笔记

一、词向量的世界排名比赛MTEB MTEB: Massive Text Embedding Benchmark 二、词向量的维数 词向量的维数d1一般取20~500之间

数据结构与算法编程题11

已知两个链表A和B分别表示两个集合&#xff0c;其元素递增排列。 请设计算法求出A与B的交集&#xff0c;并存放于A链表中。 a: 1, 2, 2, 4, 5, 7, 8, 9, 10 b: 1, 2, 3, 6, 7, 8 #include <iostream> using namespace std;typedef int Elemtype; #define ERROR 0; #defin…

基于鹈鹕算法优化概率神经网络PNN的分类预测 - 附代码

基于鹈鹕算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于鹈鹕算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于鹈鹕优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络的光滑…

Linux文件

目录 一、基本概念 二、研究进程和被打开文件的关系 &#xff08;一&#xff09;w方式 &#xff08;二&#xff09;a方式 三、认识系统接口&#xff0c;操作文件 &#xff08;一&#xff09;认识文件描述符 &#xff08;二&#xff09;举例 &#xff08;三&#xff09;…

分类预测 | Matlab实现基于PSO-PNN粒子群算法优化概率神经网络的数据分类预测

分类预测 | Matlab实现基于PSO-PNN粒子群算法优化概率神经网络的数据分类预测 目录 分类预测 | Matlab实现基于PSO-PNN粒子群算法优化概率神经网络的数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现基于PSO-PNN粒子群算法优化概率神经网络的数据…

基于材料生成算法优化概率神经网络PNN的分类预测 - 附代码

基于材料生成算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于材料生成算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于材料生成优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

Java基础(程序控制结构篇)

Java的程序控制结构与C语言一致&#xff0c;分为顺序结构、选择结构&#xff08;分支结构&#xff09;和循环结构三种。 一、顺序结构 如果程序不包含选择结构或是循环结构&#xff0c;那么程序中的语句就是顺序的逐条执行&#xff0c;这就是顺序结构。 import java.util.Sc…

linux之进程地址空间

文章目录 1.进程地址空间回顾1.1进程地址空间划分1.2验证进程地址空间划分1.简单划分2.完整划分 2.初探进程地址空间2.1初看现象2.2Makefile的简便写法 3.进程地址空间详解3.1地址空间是什么?3.2地址空间的设计/由来3.3空间区域划分3.4如何理解地址空间?3.5解释3.2的&#x1…

在中国企业出海的大浪潮下,亚马逊云科技提供遍及全球的基础设施和技术支持

中国技术出海是中国企业更高层次更高质量的全球化。在人类文明发展史上&#xff0c;凝聚中国古人智慧结晶的造纸术、印刷术、火药、指南针等&#xff0c;曾为中国技术出海写下过浓墨重彩的一笔。在今天&#xff0c;如金山办公、店匠科技、ADVANCE.AI等公司又以技术立业&#xf…

最受欢迎的猫罐头有那些?精选的5款热门猫罐头推荐!

新手养猫很容易陷入疯狂购买的模式&#xff0c;但有些品牌真的不能乱买&#xff01;现在的大环境不太好&#xff0c;我们需要学会控制自己的消费欲望&#xff0c;把钱花在刀刃上&#xff01;现在宠物市场真的很内卷&#xff0c;很多品牌都在比拼产品的数据和营养成分。很多铲屎…

如何查找批量企业的联系方式?

​我们都知道&#xff0c;企业的联系方式在企业的年报中就能找到&#xff0c;但是年报上的电话真的是你要找的吗&#xff1f; 很多企业年报上留的是第三方代记账公司&#xff0c;或者是其他没用的号码&#xff0c;这对于做B端业务的企业来说是不够精准的。 市面上有很多做企业…

redis运维(十六) 有序集合

一 有序集合 把握一点&#xff1a; 各种redis 命令都提供各种语言对应的API 接口,后续API是关键 ① 概念 1、sorted set --> 有序集合2、redis有序集合也是集合类型的一部分&#xff0c;所以它保留了集合中元素不能重复的特性3、但是不同的是,有序集合给每个元素多设置…

[Docker]九.Docker compose讲解

docker-compose 是 docker 官方的一个开源项目&#xff0c;可以实现对 docker 容器集群的快速编排, docker-compose 通过一个 配置文件 来管理多个 Docker 容器,在配置文件中&#xff0c;所有的容器通过 services 来定义&#xff0c;然后使用 docker-compose脚本 来 启动&am…

10、信息打点——APP小程序篇抓包封包XP框架反编译资产提取

APP信息搜集思路 外在——抓包封包——资产安全测试 抓包&#xff08;Fiddle&茶杯&burp&#xff09;封包&#xff08;封包监听工具&#xff09;&#xff0c;提取资源信息 资产收集——资源提取——ICO、MAD、hash——FOFA等网络测绘进行资产搜集 外在——功能逻辑 内在…

pikachu靶场PHP反序列化漏洞

pikachu靶场PHP反序列化漏洞 源码分析 查看源代码 class S{var $test "pikachu";function __construct(){echo $this->test;} }// O:1:"S":1:{s:4:"test";s:29:"<script>alert(xss)</script>";} $html; if(isset($_PO…

pikachu_php反序列化

pikachu_php反序列化 源代码 class S{var $test "pikachu";function __construct(){echo $this->test;} }//O:1:"S":1:{s:4:"test";s:29:"<script>alert(xss)</script>";} $html; if(isset($_POST[o])){$s $_POST[…

优先级队列(priority_queue)

文章目录 优先级队列的定义定义&#xff1a;接口头文件优先队列和堆的关系使用&#xff1a;排序的规则容器 仿函数应用 队列存指针问题&#xff1a; 优先级队列的定义 定义&#xff1a; 黄色部分是仿函数 接口 头文件 这里不需要包含其他的头文件只需要使用队列的头文件就可以…

SpringBoot监听器解析

监听器模式介绍 监听器模式的要素 事件监听器广播器触发机制 SpringBoot监听器实现 系统事件 事件发送顺序 监听器注册 监听器注册和初始化器注册流程类似 监听器触发机制 获取监听器列表核心流程: 通用触发条件: 自定义监听器实现 实现方式1 实现监听器接口: Order(1) …

SPSS系统聚类

前言&#xff1a; 本专栏参考教材为《SPSS22.0从入门到精通》&#xff0c;由于软件版本原因&#xff0c;部分内容有所改变&#xff0c;为适应软件版本的变化&#xff0c;特此创作此专栏便于大家学习。本专栏使用软件为&#xff1a;SPSS25.0 本专栏所有的数据文件请点击此链接下…

基于python人脸性别年龄检测系统-深度学习项目

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介简介技术组成1. OpenCV2. Dlib3. TensorFlow 和 Keras 功能流程 二、功能三、系统四. 总结 一项目简介 # Python 人脸性别年龄检测系统介绍 简介 该系统基…