Python渗透测试——一、数据包的编辑工具——Scapy
Python渗透测试
- 一、Scapy简介
- 二、Scapy中的分层结构
- 三、Scapy中的常用函数
- 四、在Scapy 中发送和接收数据包
- 五、Scapy 中的抓包函数
一、Scapy简介
提到数据包(这里泛指帧、段和报文等)的构造,我们首先需要了解协议和分层这两个概念。在“互联世界的规则一协议”中,我们提到了协议的概念,简单来说协议就是通信时所有参与者必须遵守的规则集合。这些协议各司其职、各尽其能,它们的不同主要体现在产生的数据包的顺序与格式上。
个在网络中的数据包往往会包含多个协议,例如我们所使用的 QQ,它在登录时就会产生数据包。这个数据包的目标地址是腾讯服务器(假设为 1.1.1.1),目标端口是 8000,传输的信息为“我要登录”,那么这个过程产生的数据包就需要包含 IP 部分(用来指明目标地址等信息)UDP 部分(用来指明端口等信息 、QQ 自有协议部分(用来保存传输内容等)。实际情况远比这要复杂,互联网上存在的协议数量已经成千上万了,当多个协议存在于同一个数据包时,为了解析方便,就有必要将它们分成不同的层次。
目前通用的分层方式有两种,我们以相对简单的 TCP/IP 协议族为例,它是一个4层协议模型、自底而上分别是链路层、网络层、传输层和应用层。每一层完成不同的功能,且通过若干协议来实现,上层协议使用下层协议提供的服务。
TCP/IP 协议族常见协议所属层次
这样分层之后来构造数据包就会很简单。但是需要注意,一个数据包并不是必须同时包含这 4层的协议,也不是同一层只能包含1个协议。在后面的具体实现中,我们就会对此有深入的了解。
前面提到 Scapy 是一个可以直接操作到数据包层次的工具。在 Windows 中,我们可以在Python 环境中将Scapy 当作一个库使用;如果是在 Linux中则可以将 Scapy 当作一个独立的工具来使用,它提供了一个和Python相同的交互式命令行环境。在Kali Linux2.0中已经集成了 Scapy 环境,只需要启动一个终端,输入命令“scapy”,就可以启动 Scapy编程环境。
Scapy 提供了和 Python 一样的交互式命令行。这里需要特别强调的是,虽然将 Scapy 模块作为 Python 的一个库,但是 Scapy 本身就是一个可以独立运行的工具,它具备一个独立的运行环境,因而可以不依赖Python。
二、Scapy中的分层结构
首先我们先用几个实例来演示 Scapy 的用法。Scapy 使用了“类+属性”的方法来构造数据包,在 Scapy 中每一个网络协议就是一个类,协议中的字段就对应着属性。只需要实例化一个协议类,就可以创建一个该协议类型的数据包。例如我们要构造一个 IP 数据包,可以使用如下方式。
IP()
如果要使用 IP 的话,那么首先需要导人 Scapy 库。考虑到目标模块中的属性非常多,反复输人 Scapy 很不方便,这里我们选择“from 模块 import 类”的形式导人,下面给出了一个使用Scapy构造IP 数据包的演示程序
from scapy.all import IP
pkt=IP()
print(pkt)
这个程序执行之后,可以输出中看到的结果:
对于 IP 来说,最重要的属性就是源地址和目标地址,这两个属性在 Scapy中使用参数 src和 dst来设置。例如我们要构造一个发往“192.168.217.150”的IP 数据包,就可以使用以下语句。
ip=IP(dst="192.168.217.150")
对于 Scapy 的使用者来说,比较困难的一点就是协议类型众多。现在使用IPO来构造数据包的时候,都需要设置哪些参数,这些参数都有什么意义呢?由于网络中协议数量众多,因此Scapy 在内部实现了大量的网络协议 (DNS、ARP、IP、TCP、UDP 等)。人类靠记忆来完成这个工作是很难的。
要想熟练地使用 Scapy,大家需要掌握协议的一些基础知识。另外 Scapy 也提供了一个可以便捷查看数据包格式的函数ls(),当你不了解如何为一个 IP 数据指定目标地址的时候、就可以使用下面的程序。
from scapy.all import IP,ls
pkt=IP()
ls (pkt)
执行该程序,可以看到结果。
Scapy 采用分层的方式来构造数据包,通常最底层的协议为 Ether,然后是 IP,再之后是TCP 或者 UDP。例如我们使用 Ether0,这个类可以设置发送方和接收方的 MAC 地址。那么我们现在来产生一个广播数据包,执行的命令如下。
Ether(dst="ff:ff:ff:ff:ff:ff")
分层是通过符号“/”实现的。如果一个数据包是由多层协议组合而成的,那么这些协议之间就可以使用“/”分开,并按照协议由底而上的顺序从左向右排列。例如我们可以使用Ether()/IP()/TCP()来构造一个TCP数据包。
from scapy.all import
pkt=Ether()/IP()/TCP()
ls(pkt)
这个程序由于需要导入的模块比较多,因此使用了“import *”。在执行这个程序之后,可以看到我们构造了一个包含 Ether、IP 和TCP 这3 种协议的数据包。
如果要构造一个HTTP 数据包,也可以使用以下这种方法。
三、Scapy中的常用函数
Scapy中使用频率最高的类要数 Ether IPTCP和UDP了,这些类都具有哪些属性呢?Eth类中显然具有源地址、目标地址和类型。IP类的属性则复杂了许多,除了最重要的源地址和目地址之外,还有版本、长度、协议类型、校验和等。TCP 类中具有源端口和目标端口。这里我可以使用ls()函数来查看一个类所拥有的属性。前面我们已经提过了,这个函数使用属性列表的式来显示一个数据包的详细信息,例如使用ls(Ether0)来查看 Ether 类的属性。
也可以使用同样的方法用ls(IP())来查看 IP 类的属性,可以对属性列表里对应的属性进行设置,例如我们将 ttl 的值设置为 32,就可以使用如下方式。
pkt=IP(src="192.168.1.1",dst="192.168.1.101",ttl=32)
刚开始不熟悉 Scapy 有哪些功能的时候,大家可以使用 lsc()函数列出所有可以使用的函数,下面给出了一些经常使用的函数及其使用方法。首先我们使用 pkt=IP()来构造一个数据包然后利用这个 pkt 来演示各种函数。
- raw()函数表示以字节格式来显示数据包内容。例如我们如果要查看 pkt,就可以使用 print(raw(pkt))。
- hexdump()函数表示以十六进制数据表示的数据包内容给出了print(hexdump(pkt))的执行结果。
- summary()函数使用不超过一行的摘要内容来简单描述数据包,pkt.summary()让使用者可以简单明了地知晓数据包的内容。
- show()函数使用展开视图的方式显示数据包的详细信息,是一种比较常用的方法,使用者可以快速看到每一个属性的值,给出了 pkt,show()的执行结果。
- show2()函数的作用与 show()的基本相同,区别在于使用 pkt.show2()时会显示数据包的校验和。
如果我们看到了一个数据包,但是不知道如何使用命令来产生相同的数据包时,就可以使用command()函数,它可以显示出构造该数据包的命令。例的就是用 pkt.command()还原 pkt 的构造命令。
有时使用 Scapy 会捕获到大量的数据包,这些数据包需要保存起来,例如在网络取证时就会经常这么做,这时 wrpcap()函数就可以完成这个工作。例如我们在程序中将很多数据包都临时存储在 pkts 中,使用wrpcap("temp.cap",pkts)
就可以将pkts 中的数据包写入文件 temp.cap。
同样 Scapy 也提供了读取数据包文件的功能,rdpcap()函数就可以实现这个功能,例如使用pkts =rdpcap("temp.cap")
读取 temp.cap文件中的数据包。
四、在Scapy 中发送和接收数据包
除了这些对应着协议的类和它们的属性之外,我们还需要一些可以实现各种功能的函数需要注意的一点是,刚才我们使用 IP()的作用是产生了一个 IP 数据包,但是并没有将其发送出去,因此现在首先需要将产生的数据包发送出去。Scapy 提供了多个用来发送数据包的函数先来看其中的 send()函数和 sendp()函数。这两个函数的区别在于 send()数是用来发送IP数据包的,而sendp()函数是用来发送 Ether 数据包的。我们先来构造一个目标地址为 192.168.1.1的ICMP 数据包,并将其发送出去,可以使用如下程序。
from scapy.all import *
pkt=IP(dst="192.168.217.150")/ICMP()
send(pkt)
注意,如果这个数据包发送成功,那么下方会有一个“Sent 1 packets”的显示。sendp()函数的使用方法是相同的,下面给出了一个实例。
sendp(Ether(dst="ff:ff:ff:ff:ff:ff"))
简单来说,当你需要将 MAC 地址作为目标时,就使用 sendp()函数;而当你需要将IP 地址作为目标时,就使用 send()函数。这两个函数的特点是只发不收,也就是说只会将数据包发送出去,但是不会处理该数据包的应答数据包。
在网络的各种应用中,我们需要做的不仅要将创建好的数据包发送出去,也要接收这些数据包的应答数据包,这一点在网络扫描中尤为重要。Scapy 提供了 3 个用来发送和接收数据包的丽数,分别是 sr()函数、sr1()函数和 srp()函数,其中 sr()函数和 sr1()函数主要用于 IP 地址,而srp()丽数用于MAC地址。
这里我们仍然向192.168.217.150发送一个ICMP 数据来了解 sr()函数的使用方法需要注意的是,这里 192.168.217.150 应该是一个可以 ping通的地址。
当产生的数据包被发送出去之后,Scapy 就会监听接收到的数据包,将其中对应的应答数据包筛选出来并显示。为 Reveived 表示收到的数据包个数,answers 表示对应此次发送数据包的应答数据包。
sr()函数是 Scapy 的核心,它的返回值是两个列表,第一个列表包含收到了应答的数据包和对应的应答数据包,第二个列表包含未收到应答的数据包。所以可以使用两个列表来保存sr()函数的返回值。
from scapy.all import *
pkt=IP(dst="192.168.217.150")/ICMP()
ans,uans=sr(pkt)
ans.summary()
这里我们使用ans列表和 uans列表来保存sr()函数的返回值。因为发送出去的是一个ICMP数据包,而且收到了一个应答数据包,所以这个发送的数据包和收到的应答数据包都被保存到了ans列表中使用ans.summary0可以查看两个数据包的内容。unans列表为空。为ans中保存的应答数据包。
srl()雨数跟 sr()丽数作用基本一样,但是只返回一个应答数据包,只需要使用一个列表可以保存这个雨数的返回值。srp()丽数与 srl()函数和 sr()函数的区别在于发送时要使用 MAC地址。
五、Scapy 中的抓包函数
另外,一个十分重要的函数是 snim0。如果你使用过 Tcpdump,那么对这个函数就不会感到陌生。使用这个函数就可以在自己的程序中捕获经过本机网卡的数据包了。
sniff()
这个函数完整的格式为sniff(filter="",iface="any”,prn=function,count=N)
。第1个参数是filter,可以用来对数据包进行过滤。例如我们指定只捕获与 192.168.217.150有关的数据包,就可以使用host 192.168.217.150"
sniff(filter="host 192.168.1.1")
但是这种仅依靠IP地址来过滤的方法有很大的局限性,下面我们介绍一种功能更加完善的方法。1993年史蒂文·麦卡内(Steven McCanne)与范·雅各布森( Van Jacobson)在USENIX93会议上提出了一种机制一伯克利包过滤(Berkeley Packet Filter,BPF)它采用了一种与自然语言很接近的语法,利用这种语法构成的字符串可以确定保留哪些数据包以及忽略哪些数据包。
这种语法很容易理解。例如最简单的空字符串,表示的就是匹配所有数据包,也就是保留所有的数据包。如果这个字符串不为空,那么只有那些使字符串表达式值为“真”的数据包才会被保留。这种字符串通常由一个或者多个原语所组成,每个原语又由一个标识符(名称或者数字)组成,后面跟着一个或者多个限定符。
伯克利包过滤中的限定符有下面3种:
- Type:这种限定符表示指代的对象,例如 IP 地址子网或者端口等。常见的有 host(用来表示主机名和 IP 地址)、net(用来表示子网)、port(用来表示端口)。如果没有指定,默认为 host。
- Dir:这种限定符表示数据包传输的方向,常见的有 src(源地址)和 dst(目的地)如果没有指定,则默认为“src or dst”。例如 192.168.217.151表示的就是匹配源地址或者目标地址为 192.168.217.150的数据包。
- Proto:这种限定符表示与数据包匹配的协议类型,常见的就是 Ether、IP、TCP、ARP这些协议。
伯克利包过滤中的标识符指的就是那些进行测试的实际内容,例如一个 IP 地址 192.168.217.151,一个子网192.168.217.0/24 或者一个端口号 8080,这些都是常见的标识符。host 192.168.217.151和 port 8080 是两个比较常见的原语,我们还可以用 and、or 和 not 把多个原语组成一个更复杂的过滤语句。例如host 192.168.217.151 and port 8080 就是一个符合规则的过滤语句。
下面给出了一些常见的原语实例。
- host 192.168.1.1:当数据包的目标地址或者源地址为 192.168.1.1 时,过滤语句为真。
- dst host 192.168.1.1:当数据包的目标地址为 192.168.1.1时,过滤语句为真
- src host 192.168.1.1:当数据包的源地址为 192.168.1.1 时,过滤语句为真。
- ether host 11:22:33:44:55:66:当数据包的以太网源地址或者目标地址为 11:22:33:44:55:66时,过滤语句为真。
- ether dst 11:22:33:44:55:66:当数据包的以太网目标地址为 11:22:33:44:55:66 时,过语句为真。
- ether src 11:22:33:44:55:66:当数据的以太网源地址为11:22:33:44:55:66 时过滤语句为真
- dst net 192.168.1.0/24:当数据包的IP4/IPv6 的目标地址的网络号为192.168.1.0/24时过滤语句为真。
- src net 192.168.1.0/24:当数据包的IPV4/IPv6 的源地址的网络号为19216810/24时过滤语句为真。
- net 192.168.1.0/24:当数据包的IPV4/IPV6 的源地址或目标地址的网络号为192.168.1.0/24时,过滤语句为真。
- dst port 8080:当数据是TCP 或者UDP 数据包且目标端口号为8080时过滤语为真。
- src port 8080:当数据包是TCP 或者UDP 数据包且源端口号为 8080 时,过滤语句为真。
- port 8080:当数据包的源端口或者目标端口为 8080 时,过滤语句为真。所有的 port前面都可以加上关键字TCP或者UDP。
第2个参数 iface 用来指定要使用的网卡,默认为第一块网卡。
第3个参数 prn表示对捕获到的数据包进行处理的函数,可以使用 Lambda 表达式。例如我们要将获取到的数据包输出,就可以使用以下函数。
sniff(filter="icmp", prn=lambda x:x.summary())
如果这个函数比较长,也可以定义成回调函数。这个回调函数以接收到的数据包对象作为唯一的参数,最后再调用 sniff()函数。
def packet_callback(pkt):print (pkt,summary)
sniff(prn=packet.callback)
第4个参数 count 用来指定监听到数据包的数量,达到指定的数量就会停止监听。例如我们只希望监听到 10 个数据包就停止。
sniff(count=10)
我们来设计一个综合性的监听器,它会在网卡 eth0 上监听源地址或者目标地址为 192.168.1.1 的1CMP 数据包并输出,当收到了3个这样的数据包之后,就会停止监听。建的监听器如下:
sniff(filter="icmp and host 192,168,1,1",prn=lambda x:x,summary(),count=3)
相关文章:

Python渗透测试——一、数据包的编辑工具——Scapy
Python渗透测试 一、Scapy简介二、Scapy中的分层结构三、Scapy中的常用函数四、在Scapy 中发送和接收数据包五、Scapy 中的抓包函数 一、Scapy简介 提到数据包(这里泛指帧、段和报文等)的构造,我们首先需要了解协议和分层这两个概念。在“互联世界的规则一协议”中…...

使用webstrom编写vue开启提示
1.语言服务器选择 2.文件类型–忽略的文件和文件夹,删去,node_modules,就可以点进去库了 3.禁用JSLint、TSLint 4.开启node辅助 5.如果是vite,开启自动读取,或手动指定 6.如果是Webpack,开启自动读取&#…...

linux远程桌面管理工具(xrdp)、向日葵
Windows远程桌面 linux远程桌面 使用向日葵远程桌面(手机端同理) Windows远程桌面 微软自带Remote Desktop Connection Manager (RDCMan)远程控制管理软件介绍 远程桌面连接管理器 v2.93 linux远程桌面 Windows远程桌面Ubunt…...
【力扣100】8.找到字符串中所有字母异位词
添加链接描述 class Solution:def findAnagrams(self, s: str, p: str) -> List[int]:sildingstrresult[]p.join(sorted(p))for i in range(len(s)):if len(sildingstr)<len(p):sildingstrsildingstrs[i]# print(sildingstr)if len(sildingstr)len(p):sort_sildingstr.j…...

圆通速递查询,圆通速递单号查询,用表格导出查询好的物流信息
批量查询圆通速递单号的物流信息,以表格的形式导出查询好的物流信息。 所需工具: 一个【快递批量查询高手】软件 圆通速递单号若干 操作步骤: 步骤1:运行【快递批量查询高手】软件,并登录 步骤2:点击主界…...

FLStudio中文2024中文最新汉化安装包下载
FLStudio中文21最新版本以其使用速度而闻名,是一个高度复杂的音乐制作环境。FL Studio免费,联合国音序器音频和MIDI每个复合编辑都是音乐。现代的DAW是一种非凡的野兽。首先,它在很大程度上把自己放在了(几乎)每个人记录过程的核心。其次&…...
AI:大语言模型训练方法 - 机器学习
Transformer Transformer是一种深度学习的模型架构,特别适用于自然语言处理任务。Transformer 模型的核心创新在于其 "自注意力"(Self-Attention)机制,这种机制使得模型可以有效地捕捉输入数据中的长距离依赖关系。 T…...

Linux(17):认识与分析登录档
什么是登录档 【详细而确实的分析以及备份系统的登录文件】是一个系统管理员应该要进行的任务之一。 登录档 就是记录系统活动信息的几个文件,例如:何时、何地(来源IP)、何人(什么服务名称)、做了什么动作(讯息登录啰)。 换句话说就是:记录系…...

STM32上模拟CH340芯片的功能 (一)
#虚拟串口模拟CH340# 代码gitee地址:STM32F103_CH340: 用STM32模拟ch340USB串口的功能 一、思路 1. 确定通信接口:CH340是一款USB转串口芯片,因此您需要选择STM32上的某个USB接口来实现USB通信。通常情况下,STM32系列芯片都有内…...
图论——最小生成树
图论——最小生成树 A wise man changes his mind, a fool never will 生成树 一个连通图的生成树是一个极小的连通子图,它包含图中全部的n个顶点,但只有构成一棵树的n-1条边。 最小生成树 在这些边中选择N-1条出来,连接所有的N个点。这N-1…...

C++基础 -42- STL库之list链表
———————STL库之list链表——————— 🎄 list链表的格式(需要定义头文件) list<int> data1(4, 100);list<int> data2(4, 500);🎄list链表的合并接口 🎄举例使用合并接口并且验证 data2.merge(data1);list<int>::…...
Backend - Python 序列化
目录 一、作用1:代码块存入数据库 二、作用2:前后端传递数据 (一)前端 1. JSON.stringify() 2. JSON.parse() (二)后端 1. json.dumps() (1)作用 (2)…...

初级数据结构(一)——顺序表
文中代码源文件已上传:数据结构源码 <-上一篇 NULL | 初级数据结构(二)——链表 下一篇-> 1、顺序表的特点 1.1、数组 现实中数据记录一般都记录在表格中,如进货单、菜单等,它们的最大特点就是…...

实现:切换页面切换标题,扩展 vue-router 的类型
布局容器-页面标题 网址:https://router.vuejs.org/zh/guide/advanced/meta 给每一个路由添加 元信息 数据 router/index.ts const router createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{ path: /login, component: () > im…...

已通过考试和认证注册以及后续计划表
已通过考试和认证注册以及后续计划表 软考 - 计算机技术与软件专业技术资格(水平)考试信息系统集成及服务项目管理人员工程类考试计划你关注的证书样子 软考 - 计算机技术与软件专业技术资格(水平)考试 高级 信息系统项目管理师&…...

开源计算机视觉库OpenCV详解
目录 1、概述 2、OpenCV详细介绍 2.1、OpenCV的起源 2.2、OpenCV开发语言 2.3、OpenCV的应用领域 3、OpenCV模块划分 4、OpenCV源码文件结构 4.1、根目录介绍 4.2、常用模块介绍 4.3、CUDA加速模块 5、OpenCV配置以及Visual Studio使用OpenCV 6、关于Lena图片 7、…...

使用pytorch查看中间层特征矩阵以及卷积核参数
这篇是我对哔哩哔哩up主 霹雳吧啦Wz 的视频的文字版学习笔记 感谢他对知识的分享 1和4是之前讲过的alexnet和resnet模型 2是分析中间层特征矩阵的脚本 3是查看卷积核参数的脚本 1设置预处理方法 和图像训练的时候用的预处理方法保持一致 2实例化模型 3载入之前的模型参数 4载入…...

HarmonyOS4.0从零开始的开发教程09页签切换
HarmonyOS(七)页签切换 List组件和Grid组件的使用 Tabs组件的使用 概述 在我们常用的应用中,经常会有视图内容切换的场景,来展示更加丰富的内容。比如下面这个页面,点击底部的页签的选项,可以实现“首页…...

大电流H桥电机驱动电路的设计与解析(包括自举电路的讲解,以IR2104+LR7843为例)
大电流H桥电机驱动电路的设计与解析(包括自举电路的讲解,以IR2104LR7843为例) 电机驱动板主要采用两种驱动芯片,一种是全桥驱动(如:HIP4082),一种是半桥驱动(如ÿ…...

windows11 windows 11 (win11 win 11) 怎么安装 Python3 ? numpy? sounddevice? 声音信号处理库?
首先确认要安装的 sounddevice 库,链接:https://python-sounddevice.readthedocs.io/en/0.4.6/ 根据文档,可知最新的 sounddevice 版本是 0.4.6 进入安装页面查看,发现 Newest sounddevice 可以使用 pip 安装,如下图…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题:安全。文章将详细阐述认证(Authentication) 与授权(Authorization的核心概念,对比传统 Session-Cookie 与现代 JWT(JS…...

【深度学习新浪潮】什么是credit assignment problem?
Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...

算术操作符与类型转换:从基础到精通
目录 前言:从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符:、-、*、/、% 赋值操作符:和复合赋值 单⽬操作符:、--、、- 前言:从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...

Java后端检查空条件查询
通过抛出运行异常:throw new RuntimeException("请输入查询条件!");BranchWarehouseServiceImpl.java // 查询试剂交易(入库/出库)记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...
stm32进入Infinite_Loop原因(因为有系统中断函数未自定义实现)
这是系统中断服务程序的默认处理汇编函数,如果我们没有定义实现某个中断函数,那么当stm32产生了该中断时,就会默认跑这里来了,所以我们打开了什么中断,一定要记得实现对应的系统中断函数,否则会进来一直循环…...

RabbitMQ 各类交换机
为什么要用交换机? 交换机用来路由消息。如果直发队列,这个消息就被处理消失了,那别的队列也需要这个消息怎么办?那就要用到交换机 交换机类型 1,fanout:广播 特点 广播所有消息:将消息…...