GBDoctor 架构解析:纯 Go 实现 GB28181 诊断引擎
GBDoctor 是一个 GB/T 28181 接入诊断工具,采用纯 Go 实现,零 CGO 依赖,单二进制交付。本文从整体架构、SIP 协议栈、诊断引擎、规则库、报告生成五个层面,拆解其工程实现。
- 为什么选择纯 Go
GB28181 诊断工具需要跑在集成商现场:Windows 笔记本、Linux 服务器、甚至 ARM 网关。传统方案依赖 Python + libpcap + Wireshark,部署成本高。GBDoctor 选择纯 Go:
零 CGO,交叉编译即走
单二进制,几 MB
go:embed 内嵌前端,无外部文件
内置抓包,不依赖 libpcap/WinPcap
最终产物:gbdoctor.exe 双击即用,gbdoctor 丢到服务器就能跑。
- 整体架构
cmd/gbdoctor/ # CLI 入口
internal/
sip/ # SIP 协议栈
roles.go # 模拟平台/摄像头角色
camera_listener.go # 模拟设备自动应答
invite.go # INVITE/SDP 解析
pcap.go # 内置抓包 + pcap 导出
diag/ # 体检引擎(分段推进)
rules/ # 声明式规则库(YAML)
report/ # HTML 报告生成
netdiag/ # 网络诊断
batch/ # 批量体检
compat/ # 国标兼容性
gbcode/ # 国标编码校验
web/ # Web UI + REST API
核心是 internal/sip 和 internal/diag:前者负责协议收发,后者负责诊断编排。 - SIP 协议栈:双角色模拟
GBDoctor 同时支持两种角色:
模拟上级平台:监听 5060,等待真实摄像头注册,主动发 Catalog、INVITE。
模拟摄像头:向真实平台注册,响应 Catalog、INVITE,发送 RTP。
以模拟平台为例,核心结构:
type Platform struct {
conn *net.UDPConn
devices sync.Map // deviceID -> Device
pcap *PcapWriter
}
func (p *Platform) Listen(port int) error {
addr := &net.UDPAddr{Port: port}
conn, err := net.ListenUDP("udp", addr)
if err != nil {
return err
}
p.conn = conn
go p.readLoop()
return nil
}
readLoop 解析 SIP 报文,根据 Method 分发:
REGISTER → 认证、记录设备
MESSAGE → 处理 Keepalive、Catalog 应答
INVITE → 处理点播请求
-
诊断引擎:分段推进
诊断不是一次性发一堆包,而是状态机:type Stage int
const (
StageRegister Stage = iota
StageKeepalive
StageCatalog
StageInvite
StageRTP
StageClock
StageDeviceInfo
// ...
)
type Engine struct {
stages []Stage
current Stage
results map[Stage]*Result
}
func (e *Engine) Run() {
for _, s := range e.stages {
r := e.runStage(s)
e.results[s] = r
if r.Blocking {
break // 断了,后面不测
}
}
}
每个 Stage 有超时、重试、证据收集。注册通了才测目录,目录通了才测点播——自动告诉你断在第几环。
-
规则库:YAML 声明式
规则与代码解耦,方便社区贡献:rule_id: CAT-001-DEVICEID-CASE
category: catalog
severity: blocking
trigger:
condition: "catalog_response.xml.*.DeviceID matches lowercase or invalid charset"
title: "目录报文 DeviceID 字段不规范"
explain: >
国标编码必须是 20 位数字。你返回的编码包含字母,多数上级平台会直接丢弃该通道。
advice:
- "检查设备/平台通道编码配置,确保为 20 位纯数字"
vendor_notes:
dahua: "主菜单→网络→平台接入→GB28181→通道编码"
hikvision: "配置→网络→高级配置→平台接入→视频通道编码ID"
引擎加载 YAML,在收到目录应答后逐条匹配,命中则生成问题条目。
-
报告生成:HTML 自包含
报告用 Go 的 html/template 渲染,CSS 内联,证据报文用展示,可截图、可打印 PDF。
func GenerateReport(w io.Writer, data *ReportData) error {
t, _ := template.New("report").Parse(reportTmpl)
return t.Execute(w, data)
}
报告包含:得分、环节进度条、问题列表、证据链、修复建议。 -
总结
GBDoctor 的工程核心是:纯 Go 协议栈 + 分段诊断引擎 + 声明式规则库 + 自包含报告。四者组合,让一个原本需要专家人肉分析的过程,变成可复制、可传播、可沉淀的自动化体检。
项目地址
Gitee:suoten/GBDoctor
GitHub:suoten/GBDoctor
搜不到?在 Gitee 或 GitHub 搜索:GBDoctor 或 suoten GBDoctor

浙公网安备 33010602011771号