现场只有一根 USB:桌面端与手持终端的数据怎么同步
现场没有网络、没有蓝牙,只剩一根 USB 线。本文讲桌面端与手持终端之间怎么做离线数据同步,以及同步协议为什么必须是二进制。
有些现场,联网是奢侈品。设备不让联网、现场没有可用的 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 当消息体来回发,传二进制内容要转义,体积和出错概率都会上去;定长头加二进制正文,才能稳定地传图片和附件。
五、同步策略:单向下发、双向同步与冲突处理
同步不是一个方向,按数据性质分成两类:
- 单向下发(中心端 → 手持端):技术规范、机构、用户、人员、台账主体、计量类信息。这些是”规则”,只能由中心端说了算。
- 双向同步(中心端 ⇄ 手持端):维护与保养记录、故障记录、领用归还与调动、资源状态。这些是”业务数据”,两端都会产生。
真正麻烦的是冲突:两端数据不一致怎么办。我们的做法是——按最终更改时间判定,插入判定信息并弹窗告警,由使用方确认,不做静默覆盖。静默覆盖看起来干净,但一旦覆盖错了,事后没有任何痕迹可查。
六、采集端的数据安全
- 手持端的本地数据库加密存储,登录口令以散列值保存,不留明文;
- 同步走本地连接,不依赖公网;数据是否需要出内网,按客户方制度执行;
- 数据库支持结构升级与数据清理,不必因为加密就换一次库重来一遍。
七、边界:什么时候不该这么做
这套结构不是万能答案。以下几种情况,我们会直说不用这么做:
- 现场有稳定网络、也允许联网:那就直接走服务端,不必自己造一套离线同步;
- 设备或终端拿不到协议与 SDK 文档:不要硬做逆向,这类收益和风险不成比例;
- 只需要一个网页后台、现场没有采集设备:这套”桌面端 + 手持终端 + 同步工具”是多余的;
- 要求做操作系统内核级适配与设备驱动开发:这不在我们的既有交付范围,评估时请先说明平台型号;
- 要求 7×24 现场驻场,或把现场实施责任整体转移给乙方:这类合作方式要另议。
八、一条经验
这类系统里,最值钱的不是”用了什么协议”,而是把同步这件事独立出来:它有明确的协议、明确的分片、明确的冲突处理,而不是散落在业务代码里。出问题的时候,有地方查;换终端、换字段的时候,也知道该动哪一层。
如果你手上也有”一端在现场、一端在台账”的场景,建议先把第七节的边界过一遍,再谈第一期做到哪。
需要一份写清范围的清单?把你的业务说一遍,几秒生成需求清单。