14-3_Qt 5.9 C++开发指南_QUdpSocket实现 UDP 通信_UDP 单播和广播
文章目录
- 1.UDP通信概述
- 2. UDP 单播和广播
- 2.1 UDP 通信实例程序功能
- 2.2 主窗口类定义和构造函数
- 2.3 UDP通信的实现
- 2.4 源码
- 2.4.1 可视化UI设计
- 2.4.2 mainwindow.h
- 2.4.3 mainwindow.cpp
1.UDP通信概述
UDP(User Datagram Protocol,用户数据报协议)是轻量的、不可靠的、面向数据报 (datagram)
、无连接的协议,它可以用于对可靠性要求不高的场合。与 TCP 通信不同,两个程序之间进行 UDP 通信无需预先建立持久的 socket 连接,UDP 每次发送数据报都需要指定目标地址和端口
(如图14-6 所示)。
QUdpSocket 类用于实现 UDP 通信,它从 QAbstractSocket 类继承,因而与 QTcpSocket 共享大部分的接口函数。主要区别是 QUdpSocket 以数据报传输数据,而不是以连续的数据流。发送数据报使用函数QUdpSocket::writeDatagram(),数据报的长度一般少于512 字节,每个数据报包含发送者和接收者的 IP 地址和端口等信息。
要进行 UDP 数据接收,要用 QUdpSocket::bind()函数先绑定一个端口,用于接收传入的数据报。当有数据报传入时会发射readyRead()信号,使用readDatagram()函数来读取接收到的数据报。
UDP 消息传送有单播、广播、组播三种模式,其示意图如图 14-7 所示
-
单播 (unicast)模式:一个 UDP 客户端发出的数据报只发送到另一个指定地址和端口的UDP 客户端,是一对一的数据传输。
-
广播(broadcast)模式:一个 UDP 客户端发出的数据报,在同一网络范围内其他所有的UDP 客户端都可以收到。QUdpSocket 支持IPv4 广播。广播经常用于实现网络发现的协议。要获取广播数据只需在数据报中指定接收端地址为 QHostAddress::Broadcast,一般的广播地址是 255.255.255.255
-
组播 (multicast)模式:也称为多播。UDP 客户端加入到另一个组播IP 地址指定的多播组,成员向组播地址发送的数据报组内成员都可以接收到,类似于 QQ 群的功能。QUdpSocket::joinMulticastGroup()函数实现加入多播组的功能,加入多播组后,UDP 数据的收发和UDP数据收发方法一样。
使用广播和多播模式,UDP 可以实现一些比较灵活的通信功能,而 TCP 通信只有单播模式没有广播和多播模式。所以,UDP 通信虽然不能保证数据传输的准确性,但是具有灵活性,一般的即时通信软件都是基于UDP 通信的。
QUdpSocket 类从QAbstractSocket 继承而来,但是又定义了较多新的功能函数用于实现 UDP特有的一些功能,如数据报读写和多播通信功能。QUdpSocket 没有定义新的信号。QUdpSocket的主要功能函数见表 14-6 (包括从 QAbstractSocket 继承的函数,省略了函数中的 const 关键字,省略了缺省参数)
在单播、广播和多播模式下,UDP 程序都是对等的,不像 TCP 通信那样分为客户端和服务器端。多播和广播的实现方式基本相同,只是数据报的目标IP 地址设置不同,多播模式需要加入多播组,实现方式有较大差异。
为分别演示这三种 UDP 通信模式,本节设计了两个实例。Samp14_3 实例演示 UDP 单播和广播通信,Samp14_4实例演示UDP组播通信。
2. UDP 单播和广播
2.1 UDP 通信实例程序功能
实例程序 samp14_3 实现 UDP 单播和广播,其主窗口是继承自 QMainWindow 的类,界面用UI 设计器设计。程序可以进行 UDP 数据报的发送和接收,samp14_3 的两个运行实例之间可以进行 UDP 通信,这两个实例可以运行在同一台计算机上,也可以运行在不同的计算机上。图 14-8和图14-9是samp14_3两个实例在一台计算机上运行时通信的界面。
在同一台计算机上运行时,两个运行实例需要绑定不同的端口,例如实例A 定端口 1200,实例B绑定端口 3355。实例A 向实例 B 发送数据报时,需要指定实例 B 所在主机的IP 地址、绑定端口作为目标地址和目标端口
(为了准确识别相应的客户端,与上篇中元组
的概念很相似),这样实例 B 才能接收到数据报。
如果两个实例在不同计算机上运行,则可以使用相同的端口,因为 IP 地址不同了,不会导致绑定时发生冲突。一般的UDP 通信程序都是在不同的计算机上运行的,约定一个固定的端口作为通信端口。
2.2 主窗口类定义和构造函数
主窗口是基于QMainWindow 的类 MainWindow,界面采用 UI 设计器设计。MainWindow类的定义如下(省略了 UI 设计器为 actions 和按钮生成的槽函数声明):
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>#include <QUdpSocket>
#include <QLabel>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTprivate:QLabel *LabSocketState;//socket状态显示标签QUdpSocket *udpSocket;//QString getLocalIP();//获取本机IP地址public:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:
//自定义槽函数void onSocketStateChange(QAbstractSocket::SocketState socketState);void onSocketReadyRead();//读取socket传入的数据
...private:Ui::MainWindow *ui;
};#endif // MAINWINDOW_H
QUdpSocket 类型的私有变量 udpSocket 是用于UDP 通信的 socket。
定义了两个自定义槽函数,onSocketStateChange()与 udpSocket 的 stateChange()信号关联,用于显示 udpSocket 当前的状态;onSocketReadyRead()信号与 udpSocket 的readyRead()信号关联,用于读取缓冲区的数据报。
MainWindow 的构造函数主要完成udpSocket 的创建、信号与槽函数的关联,代码如下:
MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);LabSocketState=new QLabel(QString::fromLocal8Bit("Socket状态:"));//LabSocketState->setMinimumWidth(200);ui->statusBar->addWidget(LabSocketState);QString localIP=getLocalIP();//本机IPthis->setWindowTitle(this->windowTitle()+QString::fromLocal8Bit("----本机IP:")+localIP);ui->comboTargetIP->addItem(localIP);udpSocket=new QUdpSocket(this);//用于与连接的客户端通讯的QTcpSocketconnect(udpSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(onSocketStateChange(QAbstractSocket::SocketState)));onSocketStateChange(udpSocket->state());connect(udpSocket,SIGNAL(readyRead()),this,SLOT(onSocketReadyRead()));
}
onSocketStateChange(udpSocket->state());
代码与上篇TCP通信程序里的完全一样。
2.3 UDP通信的实现
要实现UDP 数据的接收,必须先用QUdpSocket::bind()函数绑定一个端口,用于监听传入的数据报,解除绑定则使用 abort()函数。程序主窗口上的“绑定端口”和“解除绑定”按钮的响应代码如下:
void MainWindow::on_actStart_triggered()
{//绑定端口quint16 port=ui->spinBindPort->value(); //本机UDP端口if (udpSocket->bind(port))//绑定端口成功{ui->plainTextEdit->appendPlainText(QString::fromLocal8Bit("**已成功绑定"));ui->plainTextEdit->appendPlainText(QString::fromLocal8Bit("**绑定端口:")+QString::number(udpSocket->localPort()));ui->actStart->setEnabled(false);ui->actStop->setEnabled(true);}elseui->plainTextEdit->appendPlainText(QString::fromLocal8Bit("**绑定失败"));
}void MainWindow::on_actStop_triggered()
{//解除绑定udpSocket->abort(); //不能解除绑定ui->actStart->setEnabled(true);ui->actStop->setEnabled(false);ui->plainTextEdit->appendPlainText(QString::fromLocal8Bit("**已解除绑定"));
}
绑定端口后,socket 的状态变为已绑定状态“BoundState”,解除绑定后状态变为未连接状态UnconnectedState”
发送点对点消息和广播消息都使用 QUdpSocket:: writeDatagram()函数,窗口上“发送消息和“广播消息”两个按钮的代码如下:
void MainWindow::on_btnSend_clicked()
{//发送消息 按钮QString targetIP=ui->comboTargetIP->currentText(); //目标IPQHostAddress targetAddr(targetIP);quint16 targetPort=ui->spinTargetPort->value();//目标portQString msg=ui->editMsg->text();//发送的消息内容QByteArray str=msg.toUtf8();udpSocket->writeDatagram(str,targetAddr,targetPort); //发出数据报ui->plainTextEdit->appendPlainText(QString::fromLocal8Bit("[out] ")+msg);ui->editMsg->clear();ui->editMsg->setFocus();
}void MainWindow::on_btnBroadcast_clicked()
{ //广播消息 按钮quint16 targetPort=ui->spinTargetPort->value(); //目标端口QString msg=ui->editMsg->text();QByteArray str=msg.toUtf8();udpSocket->writeDatagram(str,QHostAddress::Broadcast,targetPort);ui->plainTextEdit->appendPlainText(QString::fromLocal8Bit("[broadcast] ")+msg);ui->editMsg->clear();ui->editMsg->setFocus();
}
使用writeDatagram()函数向一个目标用户发送消息时,需要指定目标地址和端口。
在广播消息时,只需将目标地址更换为一个特殊地址,即广播地址 OHostAddress::Broadcast,一般是255.255.255.255。通信演示如下图所示:
QUdpSocket 发送的数据报是 QByteArray 类型的字节数组,数据报的长度一般不超过 512 字节。数据报的内容可以是文本字符串,也可以自定义格式的二进制数据,文本字符串无需以换行符结束。
QUdpSocket 接收到数据报后发射 readyRead()信号,在关联的槽函数 onSocketReadyRead()里读取缓冲区的数据报,代码如下:
void MainWindow::onSocketReadyRead()
{//读取收到的数据报while(udpSocket->hasPendingDatagrams()){QByteArray datagram;datagram.resize(udpSocket->pendingDatagramSize());QHostAddress peerAddr;quint16 peerPort;udpSocket->readDatagram(datagram.data(),datagram.size(),&peerAddr,&peerPort);QString str=datagram.data();QString peer="[From "+peerAddr.toString()+":"+QString::number(peerPort)+"] ";ui->plainTextEdit->appendPlainText(peer+str);}
}
hasPendingDatagrams()表示是否有待读取的传入数据报。
pendingDatagramSize()返回待读取数据报的字节数。
readDatagram()函数用于读取数据报的内容,其函数原型为:
qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *address = nullptr, quint16 *port = nullptr)
输入参数data和 maxSize 是必须的,表示最多读取 maxSize 字节的数据到变量 data 里。address和 port 变量是可选的,用于获取数据报来源的地址和端口。上面的代码中使用了完整的参数形式,从而可以获得数据报来源的地址 peerAddr 和端口 peerPort。如果无需获取来源地址和端口,可以采用简略形式,即:
udpSocket->readDatagram(datagram,data(),datagram,size());
读取的数据报内容是 QByteArray 字节数组,因为本程序只是传输字符串,所以简单地将其转换为字符串即可。如果传输的是自定义格式的字符串或二进制数据,需要对接收到的数据进行解析。
2.4 源码
2.4.1 可视化UI设计
2.4.2 mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>#include <QUdpSocket>
#include <QLabel>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTprivate:QLabel *LabSocketState;//socket状态显示标签QUdpSocket *udpSocket;//QString getLocalIP();//获取本机IP地址public:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:
//自定义槽函数void onSocketStateChange(QAbstractSocket::SocketState socketState);void onSocketReadyRead();//读取socket传入的数据
//void on_actStart_triggered();void on_actStop_triggered();void on_actClear_triggered();void on_btnSend_clicked();void on_actHostInfo_triggered();void on_btnBroadcast_clicked();private:Ui::MainWindow *ui;
};#endif // MAINWINDOW_H
2.4.3 mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtNetwork>QString MainWindow::getLocalIP()
{QString hostName=QHostInfo::localHostName();//本地主机名QHostInfo hostInfo=QHostInfo::fromName(hostName);QString localIP="";QList<QHostAddress> addList=hostInfo.addresses();//if (!addList.isEmpty())for (int i=0;i<addList.count();i++){QHostAddress aHost=addList.at(i);if (QAbstractSocket::IPv4Protocol==aHost.protocol()){localIP=aHost.toString();break;}}return localIP;
}MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);LabSocketState=new QLabel(QString::fromLocal8Bit("Socket状态:"));//LabSocketState->setMinimumWidth(200);ui->statusBar->addWidget(LabSocketState);QString localIP=getLocalIP();//本机IPthis->setWindowTitle(this->windowTitle()+QString::fromLocal8Bit("----本机IP:")+localIP);ui->comboTargetIP->addItem(localIP);udpSocket=new QUdpSocket(this);//用于与连接的客户端通讯的QTcpSocketconnect(udpSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(onSocketStateChange(QAbstractSocket::SocketState)));onSocketStateChange(udpSocket->state());connect(udpSocket,SIGNAL(readyRead()),this,SLOT(onSocketReadyRead()));
}MainWindow::~MainWindow()
{udpSocket->abort();delete udpSocket;delete ui;
}void MainWindow::onSocketStateChange(QAbstractSocket::SocketState socketState)
{switch(socketState){case QAbstractSocket::UnconnectedState:LabSocketState->setText(QString::fromLocal8Bit("scoket状态:UnconnectedState"));break;case QAbstractSocket::HostLookupState:LabSocketState->setText(QString::fromLocal8Bit("scoket状态:HostLookupState"));break;case QAbstractSocket::ConnectingState:LabSocketState->setText(QString::fromLocal8Bit("scoket状态:ConnectingState"));break;case QAbstractSocket::ConnectedState:LabSocketState->setText(QString::fromLocal8Bit("scoket状态:ConnectedState"));break;case QAbstractSocket::BoundState:LabSocketState->setText(QString::fromLocal8Bit("scoket状态:BoundState"));break;case QAbstractSocket::ClosingState:LabSocketState->setText(QString::fromLocal8Bit("scoket状态:ClosingState"));break;case QAbstractSocket::ListeningState:LabSocketState->setText(QString::fromLocal8Bit("scoket状态:ListeningState"));}
}void MainWindow::onSocketReadyRead()
{//读取收到的数据报while(udpSocket->hasPendingDatagrams()){QByteArray datagram;datagram.resize(udpSocket->pendingDatagramSize());QHostAddress peerAddr;quint16 peerPort;udpSocket->readDatagram(datagram.data(),datagram.size(),&peerAddr,&peerPort);QString str=datagram.data();QString peer="[From "+peerAddr.toString()+":"+QString::number(peerPort)+"] ";ui->plainTextEdit->appendPlainText(peer+str);}
}void MainWindow::on_actStart_triggered()
{//绑定端口quint16 port=ui->spinBindPort->value(); //本机UDP端口if (udpSocket->bind(port))//绑定端口成功{ui->plainTextEdit->appendPlainText(QString::fromLocal8Bit("**已成功绑定"));ui->plainTextEdit->appendPlainText(QString::fromLocal8Bit("**绑定端口:")+QString::number(udpSocket->localPort()));ui->actStart->setEnabled(false);ui->actStop->setEnabled(true);}elseui->plainTextEdit->appendPlainText(QString::fromLocal8Bit("**绑定失败"));
}void MainWindow::on_actStop_triggered()
{//解除绑定udpSocket->abort(); //不能解除绑定ui->actStart->setEnabled(true);ui->actStop->setEnabled(false);ui->plainTextEdit->appendPlainText(QString::fromLocal8Bit("**已解除绑定"));
}void MainWindow::on_actClear_triggered()
{ui->plainTextEdit->clear();
}void MainWindow::on_btnSend_clicked()
{//发送消息 按钮QString targetIP=ui->comboTargetIP->currentText(); //目标IPQHostAddress targetAddr(targetIP);quint16 targetPort=ui->spinTargetPort->value();//目标portQString msg=ui->editMsg->text();//发送的消息内容QByteArray str=msg.toUtf8();udpSocket->writeDatagram(str,targetAddr,targetPort); //发出数据报ui->plainTextEdit->appendPlainText(QString::fromLocal8Bit("[out] ")+msg);ui->editMsg->clear();ui->editMsg->setFocus();
}void MainWindow::on_actHostInfo_triggered()
{//本机地址 按钮QString hostName=QHostInfo::localHostName();//本地主机名ui->plainTextEdit->appendPlainText(QString::fromLocal8Bit("本机主机名:")+hostName+"\n");QHostInfo hostInfo=QHostInfo::fromName(hostName);QList<QHostAddress> addList=hostInfo.addresses();//if (!addList.isEmpty())for (int i=0;i<addList.count();i++){QHostAddress aHost=addList.at(i);if (QAbstractSocket::IPv4Protocol==aHost.protocol()){QString IP=aHost.toString();ui->plainTextEdit->appendPlainText(QString::fromLocal8Bit("本机IP地址:")+aHost.toString());if (ui->comboTargetIP->findText(IP)<0)ui->comboTargetIP->addItem(IP);}}}void MainWindow::on_btnBroadcast_clicked()
{ //广播消息 按钮quint16 targetPort=ui->spinTargetPort->value(); //目标端口QString msg=ui->editMsg->text();QByteArray str=msg.toUtf8();udpSocket->writeDatagram(str,QHostAddress::Broadcast,targetPort);ui->plainTextEdit->appendPlainText(QString::fromLocal8Bit("[broadcast] ")+msg);ui->editMsg->clear();ui->editMsg->setFocus();
}
相关文章:

14-3_Qt 5.9 C++开发指南_QUdpSocket实现 UDP 通信_UDP 单播和广播
文章目录 1.UDP通信概述2. UDP 单播和广播2.1 UDP 通信实例程序功能2.2 主窗口类定义和构造函数2.3 UDP通信的实现2.4 源码2.4.1 可视化UI设计2.4.2 mainwindow.h2.4.3 mainwindow.cpp 1.UDP通信概述 UDP(User Datagram Protocol,用户数据报协议)是轻量的、不可靠的…...

【知识图谱】图数据库Neo4jDesktop的安装图文详解(小白适用)
neo4j 的安装需要有jdk环境的支持。因此在安装Neo4j之前,需要安装Java JDK。 一.安装JDK 参考文章https://blog.csdn.net/weixin_41824534/article/details/104147067?spm1001.2014.3001.5502 二.Neo4j下载 进入Neo4j官网 选择下载中心 下滑选择Neo4j Deskto…...
kafka中幂等性producer和事务性producer
幂等性producer 在Kafka中,“幂等性生产者”的概念是指一种特性,它确保消息在生产者的发送操作被重试时仅发送一次。幂等性是一种重要的特性,因为在分布式系统中,网络问题或其他故障可能导致生产者发送的消息在传输过程中失败,从而需要重新发送。如果生产者没有幂等性保证…...
静态路由 (华为设备)
默认路由:当路由器 收到目标地址不在路由表中的数据包时,将会 全部 发送 到 默认路由所定义的吓一跳 ,作为位置地址 数据包的 最后求助方式,这就是默认路由器的功能,默认路由的使用,可以大大的节省系统资源…...

Django学习笔记-默认的用户认证系统(auth)
一、Django默认的用户认证系统 Django 自带一个用户验证系统。它负责处理用户账号、组、权限和基于cookie的用户会话。 Django 验证系统处理验证和授权。简单来说,验证检验用户是否是他们的用户,授权决定已验证用户能做什么。这里的术语验证用于指代这…...
[SQL挖掘机] - 存储过程
介绍: 当你在sql中需要多次执行相同的一组sql语句时,存储过程是一个非常有用的工具。它是一段预先定义好的sql代码块,可以被命名并保存在数据库中,以便重复使用。 存储过程可以包含多个sql语句、逻辑流程、条件判断和循环等,可以…...

MySQL8.0.32详细安装教程(奶妈级手把手教你安装)
MySQL安装详解 前言 对于无论是刚开始接触编程的小伙伴,还是有了几年工作经验的程序猿(程序媛)来讲,数据库的安装一直都是一个比 较复杂的过程,安装完成以后可能会记得一段时间,但是等到我们换了一台电脑或…...

glut太阳系源码修改和对cpu占用观察
#include <GL/glut.h> static int day 100; // day 的变化:从 0 到 359 void myDisplay(void) {//glEnable(GL_DEPTH_TEST);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(75, 1, 1, 40…...
掌握NLTK:Python自然语言处理库中级教程
在之前的初级教程中,我们已经了解了NLTK(Natural Language Toolkit)的基本用法,如进行文本分词、词性标注和停用词移除等。在本篇中级教程中,我们将进一步探索NLTK的更多功能,包括词干提取、词形还原、n-gr…...

Go语言的崛起:探究越来越多公司选择Go语言的原因和优势
🌷🍁 博主猫头虎 带您 Go to Golang Language.✨✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~…...

MongoDB 6.0.8 安装配置
一、前言 MongoDB是一个基于分布式文件存储的数据库。由C语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。在高负载的情况下,添加更多的节点,可以保证服务器性能。 MongoDB 将数据存储为一个文档,数据结构由键值(key>value…...

无涯教程-Lua - nested语句函数
Lua编程语言允许在另一个循环中使用一个循环。以下部分显示了一些示例来说明这一概念。 nested loops - 语法 Lua中嵌套for循环语句的语法如下- for init,max/min value, increment dofor init,max/min value, incrementdostatement(s)endstatement(s) end Lua编程语言中的…...

如何使用vue ui创建一个项目?
首先打开cmd 输入vue ui 等待浏览器打开一个窗口,按照下图操作 在"功能页面"中,各个插件代表以下意思: Babel:Babel是一个JavaScript编译器,用于将ES6代码转换为向后兼容的JavaScript版本,以确保…...

STM32——LED内容补充(寄存器点灯及反转的原理)
文章目录 点灯流程开时钟配置IO关灯操作灯反转宏定义最后给自己说 本篇文章使用的是STM32F103xC系列的芯片,四个led灯在PE2,PE3,PE4,PE5上连接 点灯流程 1.开时钟 2.配置IO口 (1)清零指定寄存器位 (2)设置模式为推挽输…...
使用Spring Boot和EasyExcel的导入导出
在当今信息化社会,数据的导入和导出在各种业务场景中变得越来越重要。为了满足复杂的导入导出需求,结合Java编程语言、Spring Boot框架以及EasyExcel库,我们可以轻松地构建出强大而灵活的数据处理系统。本文将引导您通过一个案例学习如何使用…...

【H5移动端】常用的移动端方案合集-键盘呼起、全面屏适配、图片大小显示、300ms点击延迟、首屏优化(不定期补充~)
文章目录 前言键盘呼起问题靠近底部的输入项被键盘遮挡底部按钮被顶上去 全面屏适配图片大小显示问题解决300ms延迟首屏优化 前言 这篇文章总结了我在工作中做H5遇到的一些问题,包括我是怎么解决的。可能不是当下的最优解,但是能保证解决问题。 单位适…...

迭代器模式——遍历聚合对象中的元素
1、简介 1.1、概述 在软件开发时,经常需要使用聚合对象来存储一系列数据。聚合对象拥有两个职责:一是存储数据;二是遍历数据。从依赖性来看,前者是聚合对象的基本职责;而后者既是可变化的,又是可分离的。…...

亿赛通电子文档安全管理系统远程命令执行
人这一生,不是看你贫穷和富有,而是看你都做了些啥。 漏洞描述 亿赛通电子文档安全管理系统存在远程命令执行漏洞,攻击者通过构造特定的请求可执行任意命令 漏洞复现: 访问url: 构造payload请求 POST /solr/flow/d…...

多雷达探测论文阅读笔记:雷达学报 2023, 多雷达协同探测技术研究进展:认知跟踪与资源调度算法
多雷达协同探测技术 原始笔记链接:https://mp.weixin.qq.com/s?__biz=Mzg4MjgxMjgyMg==&mid=2247486627&idx=1&sn=f32c31bfea98b85f2105254a4e64d210&chksm=cf51be5af826374c706f3c9dcd5392e0ed2a5fb31ab20924b7dd38e1b1ae32abe9a48afa8174#rd ↑ \uparrow …...

【Redis】——AOF持久化
什么是AOF日志 AOF日志是redis为数据的持久化提供了的一个技术,日志里面记录着执行redis写命令。每当redis执行一条写命令的时候,就会将该命令记录 到AOF日志当中。当redis启动的时候,可以加载AOF日志中的所有指令,并执行这些指令恢复所有的…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...

nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...
上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式
简介 在我的 QT/C 开发工作中,合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式:工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...

图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...