完整通信实战
约 1984 字大约 7 分钟
PACSDICOMfo-dicom通信实战
2026-03-20
前面的文档已经把 DICOM 通讯里的概念、基础命令、扩展 DIMSE 命令和 Storage Commitment 分拆说明清楚了。这一篇的目标,是把这些内容重新串回一条更接近真实业务的链路,让你从“知道每个命令是什么”走到“知道整套流程怎么落地”。
1. 这篇文章解决什么问题
真实业务里的 PACS 对接,通常不会只执行一条命令,而是会经历下面这些阶段:
- 先验证本地和 PACS 能不能通信。
- 再查询目标患者、检查或序列。
- 需要时把影像检索回本地。
- 也可能把本地影像上传到 PACS。
- 如果业务要求更严格,还要继续做 Storage Commitment。
这意味着一条完整链路,往往同时包含:
2. 一个完整业务场景怎么理解
可以把最常见的业务拆成两条主线:
主线一:查询并取回影像
- 用 C-ECHO 验证链路。
- 用 C-FIND 找到目标检查和实例 UID。
- 用 C-MOVE 或 C-GET 把目标对象取回本地。
- 本地通过 C-STORE SCP 接收影像并落盘。
主线二:上传并确认对端承诺保存
- 用 C-ECHO 验证链路。
- 用 C-STORE 把对象发给 PACS。
- 用 N-ACTION 发起存储承诺请求。
- 用 N-EVENT-REPORT 接收承诺结果并回写状态。
很多系统会同时包含这两条主线,只是触发时机不同。
3. 阶段一:先把连接打通
无论做查询、检索还是上传,第一步都建议先固化节点配置:
- PACS 地址。
- PACS 端口。
- 本地 Calling AE Title。
- 远端 Called AE Title。
- 本地接收端 AE Title 与端口。
然后优先执行 6.C-ECHO。这一阶段的目标不是处理业务,而是确认:
- 地址、端口、AE Title 是否都对。
- 当前服务是否真的可达。
- 代码里用的节点配置是否和 PACS 侧白名单一致。
如果 C-ECHO 不通,后面的排查都不该继续。
4. 阶段二:先查元数据,再决定下一步
连接没问题后,通常不会立刻去取影像,而是先用 7.C-FIND 获取后续链路需要的键值。最关键的通常包括:
StudyInstanceUIDSeriesInstanceUID- 患者和检查层面的业务字段
这一步的意义有两个:
- 确认业务查询条件是否正确。
- 为后续的 C-MOVE、C-GET 或上传匹配提供稳定标识。
如果这里查不到结果,就不要直接怀疑检索或上传代码,先回头确认查询级别、返回字段和筛选条件。
5. 阶段三:根据网络条件选择检索方式
拿到查询结果后,通常要在 8.C-MOVE 和 10.C-GET 之间做选择。
选择 C-MOVE
适合下面这些情况:
- 本地有独立的接收端服务。
- PACS 可以反向连接这个接收端。
- 你希望把检索和接收职责拆开。
这种方式下,本地必须先准备好 C-STORE SCP,再发 MOVE。
选择 C-GET
适合下面这些情况:
- 网络环境不方便让 PACS 反向连接本地。
- 希望当前关联直接完成检索与回传。
- 当前请求方具备接收 C-STORE 子操作的能力。
这一步的关键不是“哪个命令更高级”,而是哪个更匹配现网部署条件。
6. 阶段四:接收端和发送端要分清
完整通信里最容易乱掉的地方,就是“当前本地到底是客户端还是服务端”。实际要分成两类:
本地作为接收端
这种情况通常出现在:
- C-MOVE 接收影像。
- C-GET 子操作接收影像。
- N-EVENT-REPORT 接收承诺结果。
此时你需要准备对应的 SCP 能力,而不仅仅是发请求的 DicomClient。
本地作为发送端
这种情况通常出现在:
- 主动用 C-STORE 上传影像。
- 主动用 N-ACTION 发起承诺请求。
此时重点是请求构造、批次跟踪和响应状态记录。
7. 阶段五:上传完成不等于流程完成
如果业务只是“把对象尽快发给 PACS”,那么 C-STORE 成功就可能已经够用。但如果业务要求“确认对端已经正式接收并承诺保存”,那么流程还要继续:
- 先通过 9.C-STORE 发送对象。
- 再通过 12.N-ACTION 发起承诺请求。
- 最后通过 13.N-EVENT-REPORT 接收结果。
这一段建议和下面三篇一起看:
8. 一个推荐的工程化顺序
如果你正在做一个完整 PACS 通信模块,比较稳妥的实现顺序通常是:
- 先固化节点配置模型。
- 单独打通 C-ECHO。
- 单独打通 C-FIND。
- 再打通 C-MOVE 或 C-GET。
- 再实现本地 C-STORE 接收端。
- 再实现本地 C-STORE 上传端。
- 最后接入 N-ACTION 和 N-EVENT-REPORT。
不要一开始就试图把“查询、检索、上传、承诺”一次写完。那样一旦失败,很难判断问题出在哪一层。
9. 一个最小分层思路
为了避免代码后期难维护,建议把完整链路拆成几层:
- 节点配置层:负责 PACS 地址、端口、AE Title、TLS 等参数。
- 客户端封装层:负责创建
DicomClient、添加请求和发送请求。 - 接收端服务层:负责 C-STORE SCP、N-EVENT-REPORT 接收等服务端行为。
- 业务编排层:负责把查询、检索、上传、承诺串成完整流程。
- 状态与日志层:负责批次号、事务号、对象 UID 和结果回写。
这几层不一定要按类名一一对应,但职责最好分开,否则排查问题时会非常痛苦。
10. 最常见的全链路问题
如果把整条链路串起来看,最常见的故障通常集中在下面几类:
- C-ECHO 不通,说明基础配置就有问题。
- C-FIND 无结果,说明查询条件或级别不对。
- C-MOVE 发出后收不到影像,通常是接收端 AE 或端口没有配置好。
- C-STORE 上传成功,但后续没有承诺结果,通常是 N-ACTION、N-EVENT-REPORT 或事务关联没做好。
- 收到了承诺回报,但本地状态没有正确更新,通常是对象级和批次级关联设计不清楚。
排查时建议永远按阶段往回退,而不是把所有问题都归到一个命令上。
11. 这篇和前面文档的关系
如果你想按“从概念到落地”的顺序读,推荐这样走:
其中 11.基础通信实战 更适合先把基础链路跑起来;这一篇更适合在你准备做一个完整 PACS 通信模块时,用来整理整体实现顺序。