DICOM:DICOM3.0网络通信协议(三)

背景:

专栏对于DICOM网络传输介绍过多次,例如DICOM:DICOM3.0网络通信协议(续)、DICOM医学图像处理:DICOM网络传输、DICOM医学图像处理:全面分析DICOM3.0标准中的通讯服务模块。此次通过对比fo-dicom与dcm4che两种开源库(也是C#与Java两大语言体系)的不同实现来实战学习一下DICOM网络传输的实现。

fo-dicom中DICOM传输的实现:

Created with Raphaël 2.1.0 Start TCPStream.BeginRead/EndRead PDU Decoder(判断Type) PDV Decoder(拼接) DIMSE Callback End

其中用到的.NET技术主要有:
1. MemoryStream,用于自由操作Socket的数据流
2. Array.Resize,用于动态读取指定字节长度的数据
3. Stream的BeginRead与EndRead,即CLR的异步I/O,用于控制整个数据流程
4. TemporaryFile.Create,用于缓存客户端的C-STORE-RQ请求

着重指出的是,fo-dicom中整个流程处理依托的是.NET平台的异步I/O,主要是NetworkStream的BeginRead和EndRead,通过解析TCP连接的Socket中传输过来的数据流(即DICOM中的Command以及DIMSE,统称为DICOM Message,详情参阅DICOM医学图像处理:DICOM网络传输),从而触发相应的操作。
【注】:虽然整个流程中,Request以及Response等消息的接收和发送都是依托异步I/O读写;但是其采用的是EndRead(BeginRead)的方式,因此依然同步执行,除了ProcessPDataTF和PerformDimseCallback采用了线程池(.NET平台提供的ThreadPool.QueueUserWorkItem,以及作者自定义的ThreadPoolQueue< int >)。
【注2】:在fo-dicom中除了.NET平台提供的ThreadPool线程池外,作者自定义了ThreadPoolQueue< int >线程池,两者比较如下:(详细的比较后续会补上

线程池 作用
ThreadPool系统线程池 用于处理SCU的Callback请求
ThreadPoolQueue< int >自定义线程池 用于管理整个SCP服务端的Callback请求处理

dcm4che中DICOM传输的实现:

dcm4che基于Java语言开发,整体流程如下:

Created with Raphaël 2.1.0 Start Association PDU Decoder(判断Type) FSM(有限状态机) DimseRSPHandler(回调) End

其中用到的Java语言特性主要有:
1. 基于enum的FSM,将各个状态的操作进行分类
2. Executor,用于启动整个DICOM消息处理流程
3. ScheduledExecutorService,用于检查各个状态是否超时

fo-dicom VS dcm4che:

两个开源库的封装方式不同,dcm4che中将主要的操作都放在了Association类中,而fo-dicom将主要的逻辑提取出来放到了DicomService类中,其DicomAssociation仅仅起到了记录数据结构的作用。因此从与DICOM协议的符合度上来说dcm4che的实现方式更贴近一些,其中Associaiton结构的定义更符合标准中对于连接的描述。
具体对比如下所示,左侧是fo-dicom开源库的整体结构(DICOM传输部分),右侧是dcm4che的实现。
DICOM:DICOM3.0网络通信协议(三)_第1张图片
两种开源库都是建立在全双工的TCP连接的Socket基础之上,主要的不同是:
1. 在fo-dicom开源库中,将各种ASCE对应的状态,以及DICOM的Command对应的具体指令的操作分别以接口的形式进行了归类,诸如IDicomServiceProvider、IDicomServiceUser,然后在DicomService中通过异步I/O方式解析DICOM消息中的指令,调用相应的接口实现;
2. 而dcm4che开源库中,将所有上述对应的操作统一放到了Association类中,在每个操作中实际上就是直接调用Association类的FSM状态机当前状态对应的相应操作,对于客户端和服务端、各种不同指令的不同操作是通过基于enum实现的FSM有限状态机来完成的,这是与fo-dicom中通过接口划分最大的区别。
DICOM:DICOM3.0网络通信协议(三)_第2张图片

综上所述,fo-dicom与dcm4che的两大DICOM开源实现库分别巧妙的利用了各自语言的特性,fo-dicom使用了CLR的异步I/O,dcm4che使用了Java的enum实现的FSM,只有掌握各自语言特性,结合对DICOM协议的深入了解,方能自由使用两种开源库。




作者:[email protected]
时间:2015-11-23

你可能感兴趣的:(java,enum,C#,clr,DICOM)