当前位置: 首页 > news >正文

Wireshark Lua 插件教程

本⽂主要介绍 Lua 脚本在 Wireshark 中的应⽤, Lua 脚本可以在 Wireshark 中完成如下功能:

  • 从⽹络包中提取数据, 或者统计⼀些数据包(Dumper)

  • 需要解析⼀种 Wireshark 不提供原⽣⽀持的协议(Dissector)

⽰例

协议解析

VREP 协议是 NOGD 框架对于 TRIP 协议的⼀种延伸和扩展. Wireshark 原⽣并不提供对于 VREP 协议的⽀持, 下图展⽰了脚本前后对⽐.

(a) VREP 原始字节流如下
VREP raw byte stream

(b) 脚本解析过后的信息
VREP with Lua script

数据流提取

Wireshark 对 RTPRTSP 均提供⽀持, 但是没提供对于 RTP over RTSP 协议的⽀持, 可以利⽤此处脚本提供的协议对此完成解析. 下图展⽰了这种差异.

(a) RTP over RTSP 原始信息
RTP over RTSP raw

(b) 脚本加强解析后的信息
RTP over RTSP with Lua

使⽤⽅法

假定你要使⽤ foo.lua 脚本

  1. 将脚本拷⻉到 Wireshark home ⽬录, 如 C:\Program\Files\Wireshark\foo.lua
  2. 修改 init.lua 脚本(C:\Program\Files\Wireshark\init.lua), 在末尾添加⼀⾏ dofile("foo.lua")
  3. 重启 Wireshark 使脚本⽣效

不同类型的脚本的使⽤⽅法:

  • Dissector 在选定的数据流中右击 -> 解码为… -> 选择脚本注册的协议, 如 RTPP.
  • Dumper 在⼯具菜单下⾯选择注册的 dumper.(如 Dump MPEG TS Packet)

解析器(Dissector)

注册新协议

注册新协议的⼀般步骤.

  1. 注册新协议

    • 基于 UDP 相对而⾔⽐较简单, 逐个解析 IP 包即可
    • 基于 TCP 解析器⽐较复杂, 需要考虑 TCP 重组(TCP Reassembly)
  2. 定义协议字段

  3. 注册协议字段

  4. 定义解析函数

  5. 注册到协议端口号

解析器代码框架

local ror = Proto("ror", "RTP over RTSP Protocol")-- 定义协议字段
local pf_ror_magic = ProtoField.uint8("ror.magic", "Magic", base.HEX)
local pf_ror_channel = ProtoField.uint8("ror.channel", "Interleaved Channel", base.HEX)
local pf_ror_length = ProtoField.uint16("ror.length", "Length")-- 注册协议字段
ror.fields = {pf_ror_magic ,pf_ror_channel ,pf_ror_length ,
}-- 在此处定义你精妙绝伦的解析函数function ror.dissector(tvbuf, pinfo, root)-- tvbuf: TCP segment-- pinfo: packet column info-- root: node info in the display zoneend-- 指定协议端⼝, 此处是tcp 端⼝
local tcp_dissector_table = DissectorTable.get("tcp.port")
tcp_dissector_table:add(554, ror)

TCP 包重组问题

作为 tcp 解析器必须要⽤能⼒处理下⾯⼏种情况

  1. TCP 数据段只含有协议数据包的前⼀部分
  2. TCP 数据段含有多个协议数据包
  3. 协议数据包在 TCP 数据段的中间部分, 因为协议包的前⼀部分可能没有被捕获到
  4. 数据包可能有被截断的情形
  5. 以上⼏种情形的任意组合

对以上问题的应对策略.

  1. 针对 4, 简单来说就是不解析切断的包(return 0)
  2. 针对 3, 解析函数必须要做⼀定的合法性检查, 如果不是属于该协议的包, 那么就丢弃该包(return 0)
  3. 针对 2, 在解析函数⾥⾯做⼀个 while 循环(return 已解析的⻓度)
  4. 针对 1, 尽最⼤可能去确定协议数据包的⻓度, 如果不能确定, 那么就返回⼀个默认值 DESEGMENT_ONE_MORE_SEGMENT

dissector 函数的返回值如下:

  1. 如果 TCP 数据段携带的数据不属于当前协议, 那么返回 0
  2. 如果需要更多的数据才能继续解析, 那么设置 desegment_len, desegment_offset, 返回值为 nil 或者已解析的⻓度都可以
  3. 如果不需要更多数据, 那么返回 nil 或者已经解析的⻓度都可以

Dumper

可以导出指定的协议字段到⽂件. 可选的字段:

  1. 来⾃预定义的字段(ip.src, tcp.port, rtsp.length)
  2. ⾃定义的字段(ror.magic)

Dumper 代码框架

-- 定义感兴趣的字段
-- wireshark 现已⽀持的协议的字段
local mpeg_pid = Field.new("mp2t.pid")
local mpeg_pkt = Field.new("mp2t")
-- ⾃定义协议的字段
local ror_channel = Field.new("ror.channel")-- 激活对话框时候的回调
local function init_payload_dump(file, filter)local tap = Listener.new(nil, filter)-- this function is going to be called once each time our filter matchesfunction tap.packet(pinfo, tvb)-- do some fancy workendretap_packets()tap:remove()
end-- 窗⼝回调
local function begin_dialog_menu()new_dialog("Dump MPEG TS Packets", init_payload_dump, "Output file", ilter")
end-- 注册窗⼝
register_menu("Dump MPEG TS Packets", begin_dialog_menu, MENU_TOOLS_UNSORTED)

样例解析

如下是⼀些解析样例.

  1. VREP Dissector
  2. RTP Over RTSP Dissector
  3. MPEG Dumper
  4. RTP over RTSP Dumper

VREP Dissector 解析样例

这个文件比较长, 请参考我的Github Repo

RTP Over RTSP Dissector 解析样例

-- 1. declare a new type of protocol
local rtpp = Proto("rtpp", "RTP over RTSP(iPanel Flavor)")-- 2. define some field into the rtpp
local pf_rtpp_magic = ProtoField.uint8("rtpp.magic", "Magic", base.HEX)local pf_rtpp_channel = ProtoField.uint8("rtpp.channel", "Interleaved Channel", base.HEX)
local pf_rtpp_length = ProtoField.uint16("rtpp.length", "Length")-- data 就是⽆法识别净荷内容的情况下简单的将其设置为⼆进制数据的⽅法
local default_parser = Dissector.get("data")-- 3. 注册新协议拥有的字段, 这些字段可作为以后抽取数据之⽤
rtpp.fields = {pf_rtpp_magic,pf_rtpp_channel,pf_rtpp_length,
}-- 前向声明
local dissect_rtpp
local rtpp_min_len = 4-- 此处处理TCP 重传的逻辑
function rtpp.dissector(tvbuf, pktinfo, root)local segment_length = tvbuf:len()local bytes_consumed = 0local reported_len = tvbuf:reported_length_remaining()if segment_length ~= reported_len then-- captured packets are being sliced/cut-off,-- so don't try to desegment/reassemblereturn 0endwhile bytes_consumed < segment_length do-- 此处会调⽤具体的解析函数local result = dissect_rtpp(tvbuf, pktinfo, root, bytes_consumed)if result == 0 thenreturn 0elseif result > 0 thenbytes_consumed = bytes_consumed + resultelsetinfo.desegment_offset = bytes_consumedresult = -resultpktinfo.desegment_len = resultreturn segment_lengthendendreturn bytes_consumed
end-- RTP over RTSP 有基本的RTSP 协议信令也有数据流,
-- 对基本的信令⽤默认的RTSP 解析器来解析
-- 对interleaved-channel 形式的按照其载荷类型来解析
dissect_rtpp = function(tvbuf, pinfo, root, offset)local msglen = tvbuf:len() - offsetdebug("sub_buf len=" .. msglen .. ", offset=" .. offset)if msglen < rtpp_min_len thendebug("sliced packet")return - DESEGMENT_ONE_MORE_SEGMENTend-- 分类解析if tvbuf:range(offset, 1):uint() ~= 0x24 then-- 以普通的rtsp 消息来解析debug("interpret packet as normal rtsp")local rtsp_dissector = Dissector.get("rtsp")-- 此处的返回值尚不清楚, 对此的处理也⽐较幼稚rtsp_dissector:call(tvbuf:range(offset, msglen):tvb(), pinfo, root)info("ret=" .. ret)return msglenelse-- interleaved-channel 形式debug("interpret packet as interleaved channel")local len_buf = tvbuf:range(offset + 2, 2)local payload_len = len_buf:uint()local packet_len = payload_len + 4debug("rtsp packet_len=" .. packet_len .. ", payload_len load=" .. pyload_len)-- ⾄少需要4 个字节才可以区分出该包是否属于RTP over RTSP 协议if msglen < packet_len thenreturn -(packet_len - msglen)end-- 添加⼀些界⾯显⽰信息root:add(pf_rtpp_magic,   tvbuf:range(offset + 0, 1))root:add(pf_rtpp_channel, tvbuf:range(offset + 1, 1))root:add(pf_rtpp_length,  len_buf)offset = offset + 4-- 取净荷的第⼀个字节来区分mpeg 和rtplocal probe_byte = tvbuf:range(offset, 1):uint()debug("probe_byte=" .. string.format( "0x%x ", probe_byte))if probe_byte == 0x47 then-- 0x47 开头的就⽤mpeg 的解析器来解析debug("raw mp2t packet, offset=" .. offset .. ", payload_len=" .. payload_len)local mpeg_dissector = Dissector.get("mp2t")while (offset + 188) <= packet_len dolocal mpeg_tvb = tvbuf:range(offset, packet_len - offset):tvb()-- 暂时不知道该函数的返回值是什么情况mpeg_dissector:call(mpeg_tvb, pinfo, root)offset = offset + 188endreturn offsetelseif probe_byte == 0x80 then-- 0x80 开头的尝试⽤rtp 来解析debug("RTP packet, offset=" .. offset .. ", payload_len=" .. payload_len)local rtp_dissector = Dissector.get("rtp")local rtp_tvb = tvbuf:range(offset, payload_len):tvb()-- 同样也是对返回值的情况不太了解.rtp_dissector:call(rtp_tvb, pinfo, root)if msglen ~= packet_len thendebug("length not match, payload_len + 4=" .. packet_len.. ", msglen=" .. msglen)endreturn packet_lenelsedefault_parser(tvbuf, pinfo, root)return packet_lenendend
end-- 将RTP over RTSP 协议注册到554 端⼝
-- 需要注意的是因为调⽤了原⽣RTSP 解析器, 所以我们的解析结果并不影响普通的rtsp 解析
tcp_dissector_table:add(554, rtpp)
tcp_dissector_table:add(2554, rtpp)
info("rtpp (RTP over RTSP) protocol registed at TCP port 554")

MPEG 流抽取器

if not GUI_ENABLED thenprint("mpeg_packets_dump.lua only works in Wireshark")return
end-- 声明要抽取的字段
local mpeg_pid = Field.new("mp2t.pid")
local mpeg_pkt = Field.new("mp2t")-- 窗口回调函数
local function init_payload_dump(file, filter)local packet_count = 0-- 对任意的udp 包进⾏过滤-- filter 为符合BPF 格式的任意过滤器local tap = Listener.new(nil, filter)local myfile = assert(io.open(file, "w+b"))-- 每次BPF 过滤器过滤出⼀个ip 包就会调⽤下⾯的函数function tap.packet(pinfo, tvb)-- 检查当前包⾥⾯是否有mpeg 包if (mpeg_pid()) thenpacket_count = packet_count + 1-- dump 出所有的mpeg 包local contents = {mpeg_pkt()}-- 逐个包输出到⽂件for i, finfo in ipairs(contents) dolocal tvbrange = finfo.rangelocal subtvb = tvbrange:tvb()myfile:write(subtvb:raw())-- myfile:flush()endendend-- re-inspect all the packets that are in the current capture, thereby-- triggering the above tap.packet functionretap_packets()-- cleanupmyfile:flush()myfile:close()tap:remove()debug("Dumped mpeg packets: " .. packet_count)
endlocal function begin_dialog_menu()new_dialog("Dump MPEG TS Packets", init_payload_dump, "Output file", "Packet filter (optional)\n\nExamples:\nip.dst == 225.1.1.4\nmp2t\nmp2t.pid == 0x300")
end-- 注册到程序菜单
register_menu("Dump MPEG TS Packets", begin_dialog_menu, MENU_TOOLS_UNSORTED)

RTP over RTSP 负载抽取

local mpeg_pid = Field.new("mp2t.pid")
local mpeg_pkt = Field.new("mp2t")
local rtp_payload = Field.new("rtp.payload")local function init_payload_dump(file, filter)local packet_count = 0local real_filter = "(rtpp.channel)"if filter ~= nil and filter ~= "" then-- 拼接⽤⼾输⼊的过滤参数real_filter = real_filter .. " and (" .. filter ..")"endlocal tap    = Listener.new(nil, real_filter)local myfile = assert(io.open(file, "w+b"))function tap.packet(pinfo, tvb)-- 检查是否有mpeg 数据包if (mpeg_pid()) thenlocal contents = {mpeg_pkt()}for i, finfo in ipairs(contents) dolocal tvbrange = finfo.rangelocal subtvb = tvbrange:tvb()myfile:write(subtvb:raw())endelse-- 检查是否是rtp 包local payload = rtp_payload()if payload thenlocal tvbrange = payload.rangelocal subtvb = tvbrange:tvb()myfile:write(subtvb:raw())endendendretap_packets()myfile:flush() myfile:close() tap:remove()
end

调试脚本

在命令⾏中启⽤ Wireshark, 然后可以在当前命令⾏中看到 Lua 脚本的打印输出. debug,warn(), info() 会输出到 Lua consolestdout

Debug Lua Script

参考链接

  • Wireshark Lua
  • Lua Dissector
  • Wireshark Lua Example

相关文章:

Wireshark Lua 插件教程

本⽂主要介绍 Lua 脚本在 Wireshark 中的应⽤, Lua 脚本可以在 Wireshark 中完成如下功能: 从⽹络包中提取数据, 或者统计⼀些数据包(Dumper) 需要解析⼀种 Wireshark 不提供原⽣⽀持的协议(Dissector) ⽰例 协议解析 VREP 协议是 NOGD 框架对于 TRIP 协议的⼀种延伸和扩展…...

【多模态大模型】GLM-4-Voice端到端语音交互机器人VoiceAI

写在前面&#xff1a;开源选手中最能打的 GLM-4-Voice&#xff0c;由智谱 AI 和清华大学共同研发&#xff0c;并发表论文 “GLM-4-Voice: Towards Intelligent and Human-Like End-to-End Spoken Chatbot”&#xff0c;旨在打造智能且类人化的端到端语音聊天机器人。GLM-4-Voi…...

Unity 列表滚动到指定位置

使用场景 策划提出需求&#xff1a;当玩家打开领奖界面时&#xff0c;奖励列表需要自动滑动到可以领奖的奖励栏处或者正在进行的任务栏处。 思路 1、将Content设置好对齐方式和锚点 子物体的预制体和Content&#xff1a;pivot轴心点设置为(0,1),并且设置为左上角对齐。 2、主…...

使用Crawlee可破题js渲染采集数据

使用 Crawlee 实现自动化爬虫流程 1. Crawlee 简介 Crawlee 是一个强大的爬虫框架&#xff0c;用于快速构建和维护可靠的爬虫。它支持多种爬虫类型&#xff0c;包括基于 Cheerio 和 Playwright 的爬虫&#xff0c;能够高效处理静态和动态网页。 2. 项目目标 通过自动化脚本实…...

小红的字母游戏(A组)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 小红有一个长度为 nnn 的字符串 sss&#xff0c;仅包含小写字母&#xff0c;小红可以选出 kkk 个字符&#xff0c;组成一个新的字符串 ttt&#xff0c;对于 ttt 的每一个字符 tit_it…...

MFC线程

创建线程 HANDLE m_hThread; m_hThread CreateThread(NULL, 0, save_snapshot, (LPVOID)this, 0, &iThreadId);开启线程循环等待 DWORD WINAPI save_snapshot(LPVOID pVoid) {while (true){//持续循环等待事件到达。接收到事件信号后才进入if。if (::WaitForSingleObjec…...

目标检测YOLO实战应用案例100讲-面向无人机图像的小目标检测

目录 知识储备 YOLO v8无人机拍摄视角小目标检测 数据集结构 环境部署说明 安装依赖 模型训练权重和指标可视化展示 训练 YOLOv8 PyQt5 GUI 开发 主窗口代码 main_window.py 使用说明 无人机目标跟踪 一、目标跟踪的基本原理 二、常用的目标跟踪算法 基于YOLOv…...

【Java分布式】Nacos注册中心

Nacos注册中心 SpringCloudAlibaba 也推出了一个名为 Nacos 的注册中心&#xff0c;相比 Eureka 功能更加丰富&#xff0c;在国内受欢迎程度较高。 官网&#xff1a;https://nacos.io/zh-cn/ 集群 Nacos就将同一机房内的实例划分为一个集群&#xff0c;一个服务可以包含多个集…...

VSCode轻松调试运行.Net 8.0 Web API项目

1.背景 我一直都是用VS来开发.NetCore项目的&#xff0c;用的比较顺手&#xff0c;也习惯了。看其他技术文章有介绍VS Code更轻量&#xff0c;更方便。所以我专门花时间来使用VS Code&#xff0c;看看它是如何调试代码、如何运行.Net 8.0 WebAPI项目。这篇文章是一个记录的过程…...

PageHelper新发现

PageHelper 背景解决reasonablepageSizeZero 背景 今天发现了一个很有趣的现象&#xff0c;接手一个很老的项目springmvc项目、使用PageHelper分页实现常见的后端接口分页功能。但是发现当页码参数大于实际的页码数时、正常不应该返回数据&#xff0c;但是目前确一直返回数据不…...

python编写liunx服务器登陆自动巡检脚本

前言&#xff1a; 用户需要一份用Python编写的Linux系统巡检脚本&#xff0c;检查内存、磁盘、CPU使用率&#xff0c;还有网络连通性。 首先&#xff0c;我得确定用户的使用场景。可能用户是系统管理员&#xff0c;需要定期监控服务器状态&#xff0c;确保系统正常运行。 或者…...

基于 Flink CDC YAML 的 MySQL 到 Kafka 流式数据集成

本教程的演示都将在 Flink CDC CLI 中进行&#xff0c;无需一行 Java/Scala 代码&#xff0c;也无需安装 IDE。 这篇教程将展示如何基于 Flink CDC YAML 快速构建 MySQL 到 Kafka 的 Streaming ELT 作业&#xff0c;包含整库同步、表结构变更同步演示和关键参数介绍。 准备阶段…...

数据结构——并查集

AcWing - 算法基础课 Acwing——合并集合 代码如下&#xff1a; #include <bits/stdc.h>using namespace std; #define fs first #define sc second #define endl \n #define all(x) x.begin(), x.end() typedef long long ll; typedef pair<int, int> PII;cons…...

详细解析d3dx9_27.dll丢失怎么办?如何快速修复d3dx9_27.dll

运行程序时提示“d3dx9_27.dll文件缺失”&#xff0c;通常由DirectX组件损坏或文件丢失引起。此问题可通过系统化修复方法解决&#xff0c;无需重装系统或软件。下文将详细说明具体步骤及注意事项。 一.d3dx9_27.dll缺失问题的本质解析 当系统提示“d3dx9_27.dll丢失”时&…...

【STL】4.<list>

list 前言list容器一.list初始化二.常用函数三.排序 总结 前言 stl系列主要讲述有关stl的文章&#xff0c;使用STL可以大大提高程序开发的效率和代码的可维护性&#xff0c;且在算法比赛中&#xff0c;STL可以帮助我们更方便地实现各种算法。提高我们的效率。 list容器 要使用…...

小程序中头像昵称填写

官方文档 参考小程序用户头像昵称获取规则调整公告 新的小程序版本不能通过wx.getUserProfile和wx.getUserInfo获取用户信息 <van-field label"{{Avatar}}" label-class"field-label" right-icon-class"field-right-icon-class"input-class&…...

vLLM服务设置开机自启动(Linux)

要在开机时进入指定的 conda 环境并启动此 vllm 服务&#xff0c;您可以通过以下步骤设置一个 systemd 服务来自动执行脚本。 一、第一步&#xff1a;创建一个启动脚本 1.打开终端并创建启动脚本&#xff0c;例如 /home/username/start_vllm.sh&#xff08;请替换 username 为…...

Cherno 游戏引擎笔记(91~111)

好久不见&#xff01; 个人库的地址&#xff1a;&#xff08;GitHub - JJJJJJJustin/Nut: The game_engine which learned from Cherno&#xff09;&#xff0c;可以看到我及时更新的结果。 -------------------------------Saving & Loading scene-----------------------…...

面试八股文--数据库基础知识总结(1)

1、数据库的定义 数据库&#xff08;DataBase&#xff0c;DB&#xff09;简单来说就是数据的集合数据库管理系统&#xff08;Database Management System&#xff0c;DBMS&#xff09;是一种操纵和管理数据库的大型软件&#xff0c;通常用于建立、使用和维护数据库。数据库系统…...

算法系列之动态规划

动态规划&#xff08;Dynamic Programming&#xff0c;简称DP&#xff09;是一种用于解决复杂问题的算法设计技术。它通过将问题分解为更小的子问题&#xff0c;并存储这些子问题的解来避免重复计算&#xff0c;从而提高算法的效率。本文将介绍动态规划的基本概念、适用场景、复…...

网站漏洞安全测试 具体渗透思路分析

渗透测试这些是经常谈到的问题了&#xff0c;我觉得当有了渗透接口测试之后你就会发现渗透测试这一方面也就是&#xff1a;1.基本漏洞测试&#xff1b;2.携带"低调"构思的心血来潮&#xff1b;3.锲而不舍的信念。我们在对网站&#xff0c;APP进行渗透测试的过程中会发…...

Spring Boot(七):Swagger 接口文档

1. Swagger 简介 1.1 Swagger 是什么&#xff1f; Swagger 是一款 RESTful 风格的接口文档在线自动生成 功能测试功能软件。Swagger 是一个规范和完整的框架&#xff0c;用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。目标是使客户端和文件系统作为服务器以同样的…...

【Mac电脑本地部署Deepseek-r1:详细教程与Openwebui配置指南】

文章目录 前言电脑配置&#xff1a;安装的Deepseek版本&#xff1a;使用的UI框架&#xff1a;体验效果展示&#xff1a;本地部署体验总结 部署过程Ollama部署拉取模型运行模型Openwebui部署运行Ollama服务在Openwebui中配置ollama的服务 后话 前言 deepseek最近火的一塌糊涂&a…...

测试的BUG分析

在了解BUG之前,我们要先了解软件测试的生命周期,因为大多数BUG都是在软件测试的过程中被发现的 软件测试的生命周期 在了解 软件测试的生命周期 之前,我们要先了解 软件的生命周期 ,虽然他们之间只差了两个字,但是差距还是很大的 首先是 软件生命周期 ,这个是站在 软件 的角…...

linux里面的过滤符号 | 是如何实现的

ls -l | grep ".txt" 的实现过程涉及无名管道的创建、进程的创建&#xff08;fork()&#xff09;以及输入输出的重定向&#xff08;dup2()&#xff09;。以下是详细的实现步骤和代码示例&#xff1a; 实现步骤 创建无名管道&#xff1a; 使用pipe()系统调用创建一个无…...

结构型模式--组合模式

概念 组合人模式是结构型设计模式的一种&#xff0c;主要是用于解决代码中出现类像树一样进行组合而出现的组合结构的相关操作问题。使其树中的任意一个节点&#xff08;无论是子节点还是父节点&#xff09;都可以使用同一套接口进行操作。 使用场景 1、如果希望我们对象组合…...

drupal可以自动将测试环境的网页部署到生产环境吗

在 Drupal 中&#xff0c;自动将测试环境的网页部署到生产环境通常是通过设置合适的开发和部署流程来实现的。这种自动化部署过程通常涉及以下几个步骤&#xff1a; 1. 版本控制&#xff08;Git&#xff09; 为了保证测试环境和生产环境的一致性&#xff0c;首先需要使用 Git…...

Android应用app实现AI电话机器人接打电话

Android应用app实现AI电话机器人接打电话 --安卓AI电话机器人 一、前言 【Dialer3.0智能拨号器】Android版手机app&#xff0c;由于采用蓝牙电话的方式来调用手机SIM卡发起呼叫、接听来电&#xff0c;并接收和处理通话的声音&#xff0c;通常我们以“蓝牙电话方案”来称呼它。 …...

【面试宝典】Java中创建线程池的几种方式以及区别

强烈推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站:人工智能 创建线程池有多种方式&#xff0c;主要通过 Java 的 java.util.concurrent 包提供的 Executors 工具类来实现。以下是几…...

【数据结构】哈希表

目录 哈希表 基本思想 基本原理 哈希表工作机制简化描述 关于查找、插入和删除 HashMap 主要成员变量 主要方法 内部实现细节 注意事项 哈希表 哈希表是一种基于哈希函数的数据结构&#xff0c;它通过键值对的形式存储数据&#xff0c;并允许通过键快速查找对应的值…...

MySQL 使用 `WHERE` 子句时 `COUNT(*)`、`COUNT(1)` 和 `COUNT(column)` 的区别解析

文章目录 1. COUNT() 函数的基本作用2. COUNT(*)、COUNT(1) 和 COUNT(column) 的详细对比2.1 COUNT(*) —— 统计所有符合条件的行2.2 COUNT(1) —— 统计所有符合条件的行2.3 COUNT(column) —— 统计某一列非 NULL 的记录数 3. 性能对比3.1 EXPLAIN 分析 4. 哪种方式更好&…...

RabbitMQ系列(一)架构解析

RabbitMQ 架构解析 RabbitMQ 是一个基于 AMQP 协议的开源消息中间件&#xff0c;其核心架构通过多组件协作实现高效、可靠的消息传递。以下是其核心组件与协作流程的详细说明&#xff1a; 一、核心组件与功能 Broker&#xff08;消息代理服务器&#xff09; RabbitMQ 服务端核…...

如何让传统制造企业从0到1实现数字化突破?

随着全球制造业不断向智能化、数字化转型&#xff0c;传统制造企业面临着前所未有的机遇与挑战。数字化转型不仅是技术的革新&#xff0c;更是管理、文化、业务流程等全方位的变革。从零开始&#xff0c;如何带领一家传统制造企业走向数字化突破&#xff0c;是许多企业领导者面…...

基于Spring Boot的二手物品交易平台设计与实现(LW+源码)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…...

释放 Cursor 的全部潜能:快速生成智能 Cursor Rules

释放 Cursor 的全部潜能&#xff1a;使用 PromptCoder 从 package.json 快速生成智能 Cursor Rules 我们将深入探讨如何利用您项目中的 package.json 文件&#xff0c;轻松生成 Cursor Rules&#xff0c;并通过 PromptCoder 这个强大的工具&#xff0c;快速创建高质量的 curso…...

C#高级:结合Linq的SelectMany方法实现笛卡尔积效果

一、笛卡尔积定义 又称直积&#xff0c;表示为X Y&#xff0c;第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员 二、基础示例 class Program {static void Main(string[] args){try{List<List<string>> input new List<List<string&g…...

【洛谷入门赛】B4018 游戏与共同语言

题意 这里有两个队伍分别叫 A 和 B。 分别给定这两个队伍的胜利数、净胜局、平局数量。 求哪个队更厉害&#xff0c;就输出哪个。 具体比较规则如下&#xff1a; 两队中胜利数高的队伍更厉害。 若胜利数相同&#xff0c;净胜数高的队伍更厉害。 若净胜数仍然相同&#x…...

Python学习总结

客户端与服务端聊天窗口 服务端 导入 wxPython 用于创建图形界面。 socket 用于网络通信&#xff0c;AF_INET 是 IPv4 地址族&#xff0c;SOCK_STREAM 表示流式套接字&#xff08;TCP&#xff09;。 利用wxPython 创建图形界面&#xff0c;并通过 socket 与服务器通信。 主要…...

android系统_模拟ZygoteServer写一个socket通信

目录 一,模拟ZygoteServer 二,Client 代表app 三,输出结果 四,结束语 一,模拟ZygoteServer ZygoteServer&#xff0c;不断的监听来自客户端的请求 package org.study.tiger;import java.io.*; import java.net.*; import java.util.concurrent.*;import java.io.*; impor…...

LangChain教程 - RAG - PDF问答

系列文章索引 LangChain教程 - 系列文章 在现代自然语言处理&#xff08;NLP&#xff09;中&#xff0c;基于文档内容的问答系统变得愈发重要&#xff0c;尤其是当我们需要从大量文档中提取信息时。通过结合文档检索和生成模型&#xff08;如RAG&#xff0c;Retrieval-Augment…...

李代数(Lie Algebras)与Attention:深度学习中的数学之美

李代数与Attention&#xff1a;深度学习中的数学之美 引言 作为一名深度学习研究者&#xff0c;您一定对Transformer模型和其中的注意力机制&#xff08;Attention&#xff09;不陌生。Attention通过查询&#xff08;Query&#xff09;、键&#xff08;Key&#xff09;和值&a…...

docker本地镜像源搭建

最近Deepseek大火后&#xff0c;接到任务就是帮客户装Dify&#xff0c;每次都头大&#xff0c;因为docker源不能用&#xff0c;实在没办法&#xff0c;只好自己搭要给本地源。话不多说具体如下&#xff1a; 1、更改docker的配置文件&#xff0c;添加自己的私库地址&#xff0c…...

监督学习单模型—线性模型—LASSO回归、Ridge回归

目标变量通常有很多影响因素&#xff0c;通过各类影响因素构建对目标变量的回归模型&#xff0c;能够实现对目标的预测。但根据稀疏性的假设&#xff0c;即使影响一个变量的因素有很多&#xff0c;其关键因素永远只会是少数。在这种情况下&#xff0c;还用传统的线性回归方法来…...

StableDiffusion打包 项目迁移 项目分发 1

文章目录 SD项目迁移前置知识webui-user.batwebui.batlaunch_utils.py 下一篇开始实践 SD项目迁移 显卡驱动更新&#xff1a;https://www.nvidia.cn/geforce/drivers/ 下载安装三个程序&#xff1a; python3.10.6: https://www.python.org/downloads/release/python-3106/gi…...

【C++】模板初阶

文章目录 一. 泛型编程1.1 什么是模板1.2 为什么要使用模板 二. 函数模板2.1 函数模板概念2.2 函数模板格式2.3 函数模板的原理2.4 函数模板的实例化2.4.1 隐式实例化2.4.2 显式实例化 2.5 模板参数的匹配原则 三. 类模板3.1 类模板的定义格式3.2 类模板的实例化3.3 在类模板外…...

STM32学习【4】ARM汇编(够用)

目录 ARM汇编语言基础写在前面 1. ARM汇编的分类2. 关于指令集指令集切换Thumb2指令集统一汇编语言&#xff08;UAL&#xff09;常用汇编指令 3. 汇编格式立即数与伪指令 4. 操作内存的汇编指令LDR&#xff1a;从内存加载数据到CPU寄存器STR&#xff1a;将数据从寄存器存储到内…...

傅里叶分析

傅里叶分析之掐死教程&#xff08;完整版&#xff09;更新于2014.06.06 要让读者在不看任何数学公式的情况下理解傅里叶分析。 傅里叶分析不仅仅是一个数学工具&#xff0c;更是一种可以彻底颠覆一个人以前世界观的思维模式。但不幸的是&#xff0c;傅里叶分析的公式看起来太复…...

Jmeter插件下载及安装

1、在Jmeter官网&#xff08;Install :: JMeter-Plugins.org&#xff09;下载所需插件 2、将下载的插件复制到jmeter文件下的lib/ext文件里&#xff08;PS&#xff1a;D:\Jmeter\apache-jmeter-5.6.2\lib\ext&#xff09; 3、打开Jmeter&#xff0c;选择 选项----Plugins Manag…...

Docker迁移/var/lib/docker之后镜像容器丢失问题

迁移/var/lib/docker时&#xff0c;如果目标目录少写一个/&#xff0c;/etc/docker/daemon.json中的data-root后面需要多加一级目录docker。 若迁移命令如下 rsync -avz /var/lib/docker /home/docker/ 在/etc/docker/daemon.json中添加如下内容 "data-root": &q…...

【C++】深入理解List:双向链表的应用

凭时间赢来的东西&#xff0c;时间肯定会为之作证。 前言 这是我自己学习C的第七篇博客总结。后期我会继续把C学习笔记开源至博客上。 上一期笔记是关于C的vector类知识&#xff0c;没看的同学可以过去看看&#xff1a;【C】探索Vector&#xff1a;灵活的数据存储解决方案-CS…...