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

news2025/4/8 16:52:09

🙌秋名山码民的主页
😂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();
}

最后

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】vector的介绍与使用

&#x1f9d1;‍&#x1f393;个人主页&#xff1a;简 料 &#x1f3c6;所属专栏&#xff1a;C &#x1f3c6;个人社区&#xff1a;越努力越幸运社区 &#x1f3c6;简 介&#xff1a;简料简料&#xff0c;简单有料~在校大学生一枚&#xff0c;专注C/C/GO的干货分…

【Vue】自定义指令

自定义指令 自定义指令就是自己定义的指令&#xff0c;是对 DOM 元素进行底层操作封装 ,程序化地控制 DOM&#xff0c;拓展额外的功能 全局定义 Vue.directive(指令名字, definition) 指令名&#xff1a;不包括v-前缀&#xff0c;使用时候包括v-&#xff0c;v-指令名defini…

VPS配置了swap没发挥作用怎么办

1 swap配置了但没用上 我的服务器内存是2G&#xff0c;装多一点东西就不够用&#xff0c;于是我给他分配了2G的swap&#xff0c;等了几小时&#xff0c;swap还是一点都没有使用 Linux中Swap&#xff08;即&#xff1a;交换分区&#xff09;&#xff0c;类似于Windows的虚拟内存…

IT变更管理实现服务台高效协同

在当今数字化时代&#xff0c;IT变更管理是IT管理员在服务台中必须面对的重要挑战之一。随着技术的不断发展和市场的快速变化&#xff0c;管理员需要定期进行IT系统和流程的变更&#xff0c;在确保业务稳定性的同时还需提高效率和准确率。 1、全方位的变更计划 IT中应该有一个全…

如何使用YOLOv8代码框架中的RT-DETR

1. RT-DETR RT-DETR是由由此&#xff0c;百度推出了——RT-DETR (Real-Time DEtection TRansformer) &#xff0c;一种基于 DETR 架构的实时端到端检测器&#xff0c;其在速度和精度上取得了 SOTA 性能。 RT-DETR开源的代码在百度自己的飞桨paddlepaddle上&#xff0c;因此非…

Confluence 未授权漏洞分析(CVE-2023-22515)

0x01 漏洞描述 Confluence 是由 Atlassian 开发的企业级协作软件。2023年10月&#xff0c;Atlassian 官方披露 CVE-2023-22515 Atlassian Confluence Data Center & Server 权限提升漏洞。攻击者可构造恶意请求创建管理员&#xff0c;从而登录系统&#xff0c;造成敏感信息…

BUUCTF [SWPU2019]神奇的二维码 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 得到的 flag 请包上 flag{} 提交。 密文&#xff1a; 下载附件&#xff0c;得到一个.png图片。 解题思路&#xff1a; 1、使用QR research扫一下&#xff0c;得到“swpuctf{flag_is_not_here}”的提示。 2、放到0…

HTML新手入门笔记整理:HTML基本介绍

网页 静态页面 仅可供用户浏览&#xff0c;不具备与服务器交互的功能。 动态页面 可供用户浏览&#xff0c;具备与服务器交互的功能。 HTML HTML&#xff0c;全称HyperText Markup Language&#xff08;超文本标记语言&#xff09;,是一种用于创建网页的标准标记语言。用于…

经典双指针算法试题(二)

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、有效三角形的个数1、题目讲解2、讲解算法原理3、代码实现 二、查找总价格为目标值的两个商…

MCU 的 TOP 15 图形GUI库:选择最适合你的图形用户界面(一)

在嵌入式系统开发中&#xff0c;选择一个合适的图形用户界面&#xff08;GUI&#xff09;库是至关重要的。在屏幕上显示的时候&#xff0c;使用现成的图形库&#xff0c;这样开发人员就不需要弄清楚底层任务&#xff0c;例如如何绘制像素、线条、形状&#xff0c;如果再高级一点…

栈和队列java实现

栈和队列都是动态集合&#xff0c;且在其上进行DELETE操作所移除的元素是预先设定的。在栈中&#xff0c;被删除的是最近插入的元素&#xff1a;栈实现的是一种后进先出&#xff08;last-in&#xff0c;first-out&#xff0c;LIFO&#xff09; 策略。在队列中&#xff0c;被删去…

问鼎web服务

华子目录 www简介常见Web服务程序介绍&#xff1a;服务器主机主要数据浏览器网址及http介绍urlhttp请求方法 http协议请求的工作流程www服务器类型静态网站动态网站 快速安装Apache安装准备工作httpd所需目录主配置文件 实验操作 www简介 Web网络服务也叫www&#xff08;world…

K8S部署mongodb-sharded-cluster(7.0.2)副本分片

添加源 helm repo add bitnami https://charts.bitnami.com/bitnami指定版本拉取 helm pull --repo https://charts.bitnami.com/bitnami mongodb-sharded --version 7.0.5安装时选择SCRAM-SHA-1默认是SCRAM-SHA-256 helm install -n prod mymongodb mongodb-sharded --value…

优先级队列(priority_queue)

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

蓝桥杯每日一题2023.11.22

题目描述 题目分析 由题目知其每个品牌积分一定小于315故直接暴力枚举每个品牌如果符合要求直接输出即可 &#xff08;答案&#xff1a;150&#xff09; #include<bits/stdc.h> using namespace std; int main() {for(int i 1; i < 315; i ){for(int j 1; j <…

三、防火墙-源NAT

学习防火墙之前&#xff0c;对路由交换应要有一定的认识 源NAT基本原理1.1.NAT No-PAT1.2.NAPT1.3.出接口地址方式&#xff08;Easy IP&#xff09;1.4.Smart NAT1.5.三元组 NAT1.6.多出口场景下的源NAT 总结延伸 ——————————————————————————————…

python实现调和反距离空间插值法AIDW

1 简介 AIDW 主要是针对 IDW 的缺点进行了改进&#xff0c;考虑了样本点与预测点的位置&#xff0c;即方向和距离&#xff0c;具体见下图&#xff1a; 2 改进 IDW 公式&#xff1a; 从IDW算法可看出&#xff0c;插值点的估算值仅与插值样本距插值点的远近相关&#xff0c;并未…

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

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

【LeetCode刷题】--40.组合总和II

40.组合总和II 本题详解&#xff1a;回溯算法 class Solution {public List<List<Integer>> combinationSum2(int[] candidates, int target) {int len candidates.length;List<List<Integer>> res new ArrayList<>();if (len 0) {return re…

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

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