ITPub博客

首页 > 应用开发 > Go语言 > JT808分包处理:那些标准没说清楚的事

JT808分包处理:那些标准没说清楚的事

原创 Go语言 作者:suoten 时间:2026-09-23 14:32:34 0 删除 编辑

JT808 协议里关于分包的定义,只有短短几句话:

当消息体属性中的长度大于 1024 字节时,终端应分包发送。分包消息的消息体前 4 字节为消息包总数和包序号。

标准没说清楚的事太多了。

问题一:分包大小是多少?

标准说“大于 1024 字节时分包”,但没说分包的单位是多少。

我一开始以为是按 1024 字节分包,后来发现不同终端厂商的实现不一样。有的按 1024 字节,有的按 512 字节,有的按 256 字节。更离谱的是,有些终端按“行”分包,比如一条位置数据一行,几行凑够一个包就发。

这就导致一个问题:你不知道下一个包什么时候来,也不知道要等多少个包才能拼出完整消息。

问题二:分包超时怎么处理?

如果终端发送了第 1 包和第 2 包,但第 3 包丢了,怎么办?

标准没说。你只能自己设超时。但超时设多少?设短了,终端网络慢,正常分包还没发完就被丢弃;设长了,内存里积压一堆半成品包,迟早 OOM。

JTE 在 pkg/jt808 里维护了一个 PacketCache,以终端手机号为 key,缓存分包消息。超时时间默认是 30 秒,可配置。

type PacketCache struct {
    total    uint16
    received map[uint16][]byte
    lastSeen time.Time
}

每次收到分包,更新 lastSeen。后台 goroutine 定期扫描,超过 30 秒还没收齐的,清理掉。

问题三:分包序号从几开始?

标准说“包序号”,但没说从 0 还是从 1 开始。

我见过从 0 开始的,也见过从 1 开始的。更坑的是,同一厂商的不同型号终端,有的从 0 开始,有的从 1 开始。

你只能做一个兼容:无论从 0 还是从 1,都按序拼接。

func (c *PacketCache) Add(seq uint16, data []byte) ([]byte, bool) {
    c.received[seq] = data
    if len(c.received) == int(c.total) {
        var full []byte
        for i := uint16(1); i <= c.total; i++ {
            if p, ok := c.received[i]; ok {
                full = append(full, p...)
            } else if p, ok := c.received[i-1]; ok {
                full = append(full, p...)
            }
        }
        return full, true
    }
    return nil, false
}

这段代码很丑,但能跑。后来 JTE 把序号基准做成了配置项,不同厂商配不同的基准。

问题四:分包消息 ID 相同吗?

标准说“分包消息的消息体前 4 字节为消息包总数和包序号”,但没说分包消息的消息 ID 是否相同。

实际上,同一个完整消息的所有分包,消息 ID 是一样的。但消息流水号呢?

标准没说。有的终端所有分包用同一个流水号,有的每个分包用不同的流水号。

JTE 的处理方式是:以终端手机号 + 消息 ID+ 流水号为 key 做缓存。如果流水号不同,就退化为只按手机号 + 消息 ID 缓存,但加一个超时。

问题五:分包和粘包混在一起怎么办?

最恶心的情况:终端发了一个分包,紧接着又发了另一个完整消息。两个消息粘在同一个 TCP 包里。

你需要在解析帧的时候,先按 0x7e 切分,然后对每一帧判断是分包还是完整消息。

JTE 的 FrameReader 在切分帧之后,会检查消息体属性里的分包标志位。如果是分包,交给 PacketCache;如果不是,直接交给业务处理。

总结

JT808 分包处理,标准只给了骨架,血肉要自己填。不同终端厂商的实现差异,让这件事变得特别麻烦。

如果你在做 JT808 解析,建议:

  • 分包超时做成可配置,默认 30 秒
  • 分包序号基准做成可配置,兼容 0 和 1
  • 分包缓存以终端手机号为 key,限制最大缓存数量
  • 对异常分包(总数超过 100、序号越界)做丢弃处理
  • 写单元测试覆盖各种边界场景

JTE 把这些逻辑封装在 pkg/jt808 和 module-adapter 中,可以作为实现参考。

项目仓库:

Gitee:suoten/jt-engine GitHub:suoten/JTEngine

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70050062/viewspace-3183629/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2026-05-07

  • 博文量
    69
  • 访问量
    55238