2. DICOM协议栈与网络通信基础

DICOM网络服务并不是“直接调用一个接口就能传图”的黑盒。它建立在标准TCP/IP之上,并在TCP之上叠加了一层专门负责“谁和谁通信、能做什么、如何协商”的协议——DICOM Upper Layer Protocol(DUL,上层协议)。理解这一层,是排查关联失败、传输中断、超时等问题的前提。

一、协议栈分层:DICOM消息如何落到网线上

从应用视角看,一次C-STORE或C-FIND请求,其数据要经过如下层次向下封装,再在对端逐层解封装:

  • DICOM应用层:DIMSE服务元素(C-STORE、C-FIND、C-MOVE、C-ECHO等),定义操作语义与数据集。
  • DUL(Upper Layer Protocol):负责关联建立/释放、PDU封装与解析、超时与中止处理。
  • TCP:提供面向连接的可靠字节流,默认端口104(DICOM保留端口),也常用11112等非特权端口。
  • IP:寻址与路由,决定AE之间能否在网络层互通。

关键点在于:DUL并不关心医学图像内容,它只关心“连接是否已建立、对方接受了哪些表示上下文、当前PDU是否完整”。因此,很多“传图失败”其实发生在DUL层,而非图像编码层。

二、PDU结构:DUL的“信封”

DUL在TCP字节流之上定义了多种PDU(Protocol Data Unit)。每个PDU都以统一的头部开始,结构固定:

字段长度说明
PDU类型1字节如0x01关联请求、0x02关联接受、0x04 P-DATA、0x05释放请求、0x07中止
保留字节1字节固定为0x00
PDU长度4字节大端序,表示后续数据长度
PDU数据可变随类型不同而不同

常见PDU类型包括:A-ASSOCIATE-RQ(关联请求)、A-ASSOCIATE-AC(关联接受)、A-ASSOCIATE-RJ(关联拒绝)、P-DATA-TF(数据传输)、A-RELEASE-RQ/AC(释放请求/响应)、A-ABORT(中止)。其中P-DATA-TF承载真正的DIMSE消息,是数据量最大的PDU。

PDU长度字段使用大端序(Big-Endian),而DICOM数据集中的数值编码则取决于传输语法。两者不要混淆,这是解析抓包时常见的错误来源。

三、关联建立:协商表示上下文

关联(Association)是DICOM通信的基本会话单元。建立过程如下:

  1. 请求方(SCU)向接受方(SCP)发起TCP连接,目标IP与端口来自配置。
  2. SCU发送A-ASSOCIATE-RQ,其中包含:调用AE标题、被调用AE标题、应用上下文(固定为DICOM应用上下文)、以及一个或多个表示上下文(Presentation Context)。
  3. 每个表示上下文包含:上下文ID(奇数)、抽象语法(如CT图像存储SOP类)、一个或多个传输语法(如Implicit VR Little Endian、Explicit VR Little Endian、JPEG Baseline)。
  4. SCP返回A-ASSOCIATE-AC,对每个表示上下文给出“接受”或“拒绝”,并选定一个传输语法;若全部拒绝或AE标题不匹配,则返回A-ASSOCIATE-RJ。

这里有一个工程上极易踩坑的细节:抽象语法与传输语法必须同时匹配。例如SCU只提供JPEG Baseline,而SCP只接受Explicit VR Little Endian,则对应表示上下文被拒绝,后续C-STORE会因“无可用上下文”而失败。排查时应先确认双方SOP类与传输语法列表的交集。

DICOM关联建立与释放时序(SCU ↔ SCP) SCU(请求方) SCP(接受方) TCP三次握手(端口104/11112) A-ASSOCIATE-RQ(AE标题 + 表示上下文列表) A-ASSOCIATE-AC(接受/拒绝 + 选定传输语法) P-DATA-TF(C-STORE-RQ + 数据集) P-DATA-TF(C-STORE-RSP,状态0x0000成功) A-RELEASE-RQ A-RELEASE-RP TCP连接关闭 异常分支 A-ABORT 或超时断开

四、数据传输与释放

关联建立后,双方进入数据传输阶段。DIMSE消息被封装进P-DATA-TF PDU,每个P-DATA-TF可携带一个PDV(Presentation Data Value),PDV中包含上下文ID、消息控制头(命令或数据标志)以及实际数据。由于TCP是字节流,DUL必须根据PDU长度字段正确切分,不能假设一次recv就收到完整PDU。

传输完成后,由任一方发起A-RELEASE-RQ,对方回A-RELEASE-RP,随后关闭TCP连接。若中途出现协议错误、超时或无法恢复的异常,则发送A-ABORT并直接断开。工程上应区分“正常释放”与“异常中止”:前者说明会话完整结束,后者往往意味着对端崩溃、网络中断或DUL实现不兼容。

五、工程排查要点

当关联失败时,建议按以下顺序定位:

  • 网络层:用telnet <IP> <port>或Test-NetConnection确认TCP可达。
  • AE标题:确认SCU配置的Called AE Title与SCP白名单一致,大小写与空格敏感。
  • 表示上下文:核对SOP类与传输语法交集,必要时在SCU侧增加Explicit VR Little Endian作为兜底。
  • PDU解析:抓包时关注A-ASSOCIATE-RJ的原因码(1=拒绝永久、2=拒绝临时、3=拒绝服务用户)以及A-ABORT的来源与原因。
  • 超时参数:DUL关联超时、P-DATA超时、释放超时需与对端匹配,避免一方已释放而另一方仍在发送。
不要用“ping通”代替DICOM连通性验证。ping只证明IP可达,而DICOM关联还依赖端口监听、AE标题匹配、表示上下文协商。正确的验证工具是C-ECHO(DICOM Ping)。