技术笔记

现场只有一根 USB:桌面端与手持终端的数据怎么同步

现场没有网络、没有蓝牙,只剩一根 USB 线。本文讲桌面端与手持终端之间怎么做离线数据同步,以及同步协议为什么必须是二进制。

2026 年 9 月 26 日 · 技术笔记

有些现场,联网是奢侈品。设备不让联网、现场没有可用的 Wi-Fi、连蓝牙都没有——只剩一根 USB 线。这篇文章讲我们做过的一套「桌面端 + 手持终端」系统:现场离线采集的数据,怎么回到中心端;以及「这条数据到底同没同步上」这个问题,怎么做到有确定答案。

一、先定一个前提:离线不是兜底,是常态

采集端不联网

这套系统由两部分组成:中心端的桌面应用,负责录入、组织、检索与维护台账;手持终端的采集端,负责在现场录入与查看。采集端在需求里就写明不能联网——它录入的数据、查看的数据,全部是本地数据。

这个前提不是”网络不好时的降级方案”,而是业务本身的要求:现场没有可用网络,或者数据不允许出内网。

真正的问题有三个,而且会同时发生

  • 采集与台账两张皮:手持终端采完,回到中心端还要人工二次录入。两次经手,就有两次出错机会;台账数据一错,后面的检索、统计、上报全部跟着错。
  • 网络不可控:现场没有网络,只能离线跑,等回到能连的地方再同步。
  • 规则两端不一致:中心端有固定的字段体系与编码规则,手持端如果不同步这一套规则,采回来的数据就对不上。

把这三件事拆开做,最后一定会卡在同一句话上:这条数据到底同没同步上?

二、链路为什么走 USB,而不是 Wi-Fi 或蓝牙

现场条件决定。我们做过的现场只有 USB 可用,没有蓝牙,Wi-Fi 不可控。所以链路是:

USB 连接 → ADB 通道(端口转发)→ 本机 Socket 长连接

要把这句话说准确:我们没有自己写 USB 驱动,也没有自定义 USB 协议。ADB 本身就跑在 USB 上,我们用的是「USB 连接的 ADB 通道」做端口转发——把手持终端上的端口映射到桌面端的本机端口,再在这条本地 Socket 上跑自己的同步协议。

这样做的直接好处是:整条链路不依赖现场网络,绕开了”现场 Wi-Fi 时好时坏”这类不可控因素;PC 侧的驱动安装也做成了检测加离线安装,现场没有外网也能装。

三、桌面端为什么常常是”桌面软件”而不是网页

中心端在这种场景里,需要直连本机的 USB 通道、读写本地文件,还可能在完全没有外网的环境里运行。所以它不是一个网站,而是一个桌面应用。这套桌面端已在麒麟操作系统(x86_64)环境交付上线。

我们做过的形态是 Java 桌面外壳 + 内嵌浏览器内核(JCEF / CEF)承载业务界面:

  • 界面是本地页面(随程序分发,不依赖外网),用前端技术写;
  • 页面与 Java 之间通过消息路由双向调用:页面有需要就调 Java 的一个入口,Java 处理完再回推结果;
  • 界面归前端、能力归 Java,两侧各自演进,不必互相绑死。

配套的同步工具是另一个独立程序,外壳用 JavaFX WebView 加一个本地 HTTP 服务。之所以把同步从业务里拆出来,是因为它要处理的问题(连接、分片、断点、冲突)自成一套逻辑——塞进业务代码里,最后没人说得清哪条数据同步到了哪一步。

四、同步协议:为什么用二进制,而不是把 JSON 来回发

这套链路要传的不只是表单字段,还有图片、附件和大表。所以协议是定长消息头 + 二进制正文:

  • 消息头固定 500 字节,内容是 JSON 文本,写清楚类型、文件名、总长度、偏移量、本段长度;
  • 正文是二进制,长度由头部里的 length 字段指定;
  • 接收端按 length 切片——网络流是连续的,不按长度切就会”粘包”,把两条消息粘成一条读错;
  • 文件按固定分片大小(128KB)传输,每片带 offset 与 totalBytes,中断了可以从断点续传,不必整个文件重来。

一句话:把 JSON 当消息体来回发,传二进制内容要转义,体积和出错概率都会上去;定长头加二进制正文,才能稳定地传图片和附件。

五、同步策略:单向下发、双向同步与冲突处理

同步不是一个方向,按数据性质分成两类:

  • 单向下发(中心端 → 手持端):技术规范、机构、用户、人员、台账主体、计量类信息。这些是”规则”,只能由中心端说了算。
  • 双向同步(中心端 ⇄ 手持端):维护与保养记录、故障记录、领用归还与调动、资源状态。这些是”业务数据”,两端都会产生。

真正麻烦的是冲突:两端数据不一致怎么办。我们的做法是——按最终更改时间判定,插入判定信息并弹窗告警,由使用方确认,不做静默覆盖。静默覆盖看起来干净,但一旦覆盖错了,事后没有任何痕迹可查。

六、采集端的数据安全

  • 手持端的本地数据库加密存储,登录口令以散列值保存,不留明文;
  • 同步走本地连接,不依赖公网;数据是否需要出内网,按客户方制度执行;
  • 数据库支持结构升级与数据清理,不必因为加密就换一次库重来一遍。

七、边界:什么时候不该这么做

这套结构不是万能答案。以下几种情况,我们会直说不用这么做:

  1. 现场有稳定网络、也允许联网:那就直接走服务端,不必自己造一套离线同步;
  2. 设备或终端拿不到协议与 SDK 文档:不要硬做逆向,这类收益和风险不成比例;
  3. 只需要一个网页后台、现场没有采集设备:这套”桌面端 + 手持终端 + 同步工具”是多余的;
  4. 要求做操作系统内核级适配与设备驱动开发:这不在我们的既有交付范围,评估时请先说明平台型号;
  5. 要求 7×24 现场驻场,或把现场实施责任整体转移给乙方:这类合作方式要另议。

八、一条经验

这类系统里,最值钱的不是”用了什么协议”,而是把同步这件事独立出来:它有明确的协议、明确的分片、明确的冲突处理,而不是散落在业务代码里。出问题的时候,有地方查;换终端、换字段的时候,也知道该动哪一层。


如果你手上也有”一端在现场、一端在台账”的场景,建议先把第七节的边界过一遍,再谈第一期做到哪。

需要一份写清范围的清单?把你的业务说一遍,几秒生成需求清单。