GBDoctor 架构解析:纯 Go 实现 GB28181 诊断引擎

GBDoctor 是一个 GB/T 28181 接入诊断工具,采用纯 Go 实现,零 CGO 依赖,单二进制交付。本文从整体架构、SIP 协议栈、诊断引擎、规则库、报告生成五个层面,拆解其工程实现。

  1. 为什么选择纯 Go
    GB28181 诊断工具需要跑在集成商现场:Windows 笔记本、Linux 服务器、甚至 ARM 网关。传统方案依赖 Python + libpcap + Wireshark,部署成本高。GBDoctor 选择纯 Go:

零 CGO,交叉编译即走

单二进制,几 MB

go:embed 内嵌前端,无外部文件

内置抓包,不依赖 libpcap/WinPcap

最终产物:gbdoctor.exe 双击即用,gbdoctor 丢到服务器就能跑。

  1. 整体架构
    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:前者负责协议收发,后者负责诊断编排。
  2. 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 → 处理点播请求

  1. 诊断引擎:分段推进
    诊断不是一次性发一堆包,而是状态机:

    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 有超时、重试、证据收集。注册通了才测目录,目录通了才测点播——自动告诉你断在第几环。

  1. 规则库: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,在收到目录应答后逐条匹配,命中则生成问题条目。
  1. 报告生成: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)
    }
    报告包含:得分、环节进度条、问题列表、证据链、修复建议。

  2. 总结
    GBDoctor 的工程核心是:纯 Go 协议栈 + 分段诊断引擎 + 声明式规则库 + 自包含报告。四者组合,让一个原本需要专家人肉分析的过程,变成可复制、可传播、可沉淀的自动化体检。

项目地址
Gitee:suoten/GBDoctor
GitHub:suoten/GBDoctor
搜不到?在 Gitee 或 GitHub 搜索:GBDoctor 或 suoten GBDoctor

posted @ 2026-09-18 10:27  硕腾  阅读(3)  评论(0)    收藏  举报