dicom(mDCM)中的UserIdentity字段

背景:

5月份的前半段好懒惰,手里积攒了好多篇文章,也有之前答应过博友要写的,迟迟未动笔。究其根源,有些许懒惰,但更多的是迷惑和一知半解,虽想写但却不知如何入手,零星的感悟要积累成文还是需要时间去沉淀的,以期尽量做到每篇博文有理有据。今天正好借着手头新任务的机会,介绍一下DICOM3.0标准中的又一新内容。继之前两篇博文基于JMeter+dcm4che2测试PACS服务器性能的解决方案(前/续篇)中提到的DICOM标准第15部分中的TransferCapability概念,本篇介绍中A-ASSOCIATE-RQ中的UserInformation,以及其扩展UserIdentity()此外,在文章后半段,会通过对比dcm4che2与fo-dicom(mDCM)的实现,同时借助于RawCap+WireShark对实际数据包进行分析,给出扩展UserInformation的实现。

UserInformation:

关于UserInformation的详细介绍在,其属于A-ASSOCIATE-RQ PDU结构子项。A-ASSOCIATE-RQ PDU的Application Context以及Presentation Context两个子项之前介绍比较多,且与DICOM连接Association建立密切相关。对于User Information子项介绍的不多,该子项以0x50H为标志,内部可进一步扩展子项,范围从0x51H-0xFFH。在第8部分的附录D中只是简略的介绍了Maximum length子项,起始标志为0x51H。该项用于约束连接双方传递数据包P-DATA-TF的最大长度。关于UserInformation项,标准中有两条注意事项:

1. The values of the Sub-Items types in the User Information Field are assigned by this standard in the range of 51H through FFH. Sub-Item values are defined by PS 3.7 and PS 3.8. 2. Succeeding editions of the Standard may define additional user information Sub-Items in a manner that does not affect the semantics of previously defined Sub-Items. Association acceptors compliant to an earlier edition of the Standard are required to ignore such unrecognized user information Sub-Items and not reject an Association because of their presence.

由上述注意事项可知,之前鲜有涉猎UserInformation字段而并未影响我们完成DIMSE中的各种服务是因为“标准中提到后续更新的版本中会加入对自定义扩展的说明,对于符合早期DICOM标准的终端(即A-ASSOCIATE-RQ接收方)需要自动忽略无法识别的UserInformation子项,而不应该因为存在无法识别的子项而拒绝连接请求。”

UserIdentity:

DICOM标准第8部分在A-ASSOCIATE-RQ PDU结构体中介绍了User Information项目,作为A-ASSOCIATE-RQ PDU的一部分,对于用户自定义扩展并未做深入讨论。既然标准提到了扩展子项可以从0x51H-0xFFH,是不是我们可以任意扩展呢?原则上是可以任意扩展的,只要确保Associate连接双方约定好解析方式即可。其实在DICOM3.0标准第7部分的附录中对于UserInformation中常见的扩展有更详细的介绍。在附录中D.3中详解介绍了几种常见的扩展,诸如以0x51H开头的Max PDU Length,以0x52H开头的Implentation Identification Notification,以0x53H开头的Asynchronous Operations Windows Negotiation,,以0x54H开头的SCP/SCU Role Selection Negotiation,以0x56H开头的Service-Object Pair Class Extended Negotiation,以0x57H开头的Service-Object Pair Class Common Extended Negotiation,以0x58H开头的User identity Negotiation等等,【注1】:在与0x52H开始的Implentation Identification Notification包含了两个子项,其中0x52H对应于Implentation Class UID,0x55H对应于Implentation Version Name。【注2】:在关于UserIdentity扩展字段中,其实包括以0x58H开始的UserIdentityRQ,和以0x59H开始的UserIdentityAC。

近期在项目中要同时使用到fo-dicom(前身是mDCM)和dcm4che2工具包,且需要完成两者之间数据互传,按照之前对DICOM开源库的了解,以为只要配置完成AE Title、IP和Port后即可顺利实现,但是在尝试了几天未果。通过仔细分析dcm4che2附带工具包dcmsnd.bat以及dcmqr.bat,又让我重新阅读了DICOM协议的部分章节,因此也就有了此篇博文。问题描述:使用fo-dicom开源库实现的客户端,诸如CStoreClient,向基于dcm4che2实现的dcm4chee服务器发送DCM数据,在配置完成AETitile、IP以及Port后,体会无法建立连接。

扩展fo-dicom(mDCM):RawCap+WireShark抓包分析:

如上图所示是使用RawCap+WireShark抓取的dcmsnd.bat工具包向基于fo-dicom搭建的PACS服务器发送数据数据包。之所以如此操作,谁因为使用fo-dicom构建的CStoreClient无法顺利向基于dcm4che2的dcm4chee服务器发送数据。我们反向操作发现,竟然可以顺利成功。这说明dcm4che实现的dcmsnd.bat工具包发送的数据量可能比我们使用fo-dicom的CStoreClient要大,可能包含了额外的数据。通过分析上图可以发现,多出来的部分就是以0x58H开头的UserIdentity自扩展子项,从我的专栏文章也可以知道之前在介绍dcmtk、fo-dicom、mDCM时并未涉及到该自定义字段。而dcm4che2工具包内部却对其进行了实现,并且在基于dcm4che2搭建的dcm4chee服务端中还通过该扩展字段进行了连接屏蔽(貌似这不符合我们之前看到的标准备注中提到的“服务端要忽略无法识别字段,而不应该拒绝连接”的说明。想想dcm4chee之所以如是操作,大抵也是为了增加安全性。

dcm4che2工具分析:

既然已经找到了问题原因,接下来让我们分析一下dcm4che2,找出解决方案。dcm4che2工具包中对于PDU数据结构的定义在PDUEncoder.java文件中。此外在ItemType.java类中预定了各种扩展字段类型枚举变量,具体代码如下:

class ItemType {public static final int APP_CONTEXT= 0x10;public static final int RQ_PRES_CONTEXT = 0x20;public static final int AC_PRES_CONTEXT = 0x21;public static final int ABSTRACT_SYNTAX = 0x30;public static final int TRANSFER_SYNTAX = 0x40;public static final int USER_INFO= 0x50;public static final int MAX_PDU_LENGTH = 0x51;public static final int IMPL_CLASS_UID = 0x52;public static final int ASYNC_OPS_WINDOW = 0x53;public static final int ROLE_SELECTION = 0x54;public static final int IMPL_VERSION_NAME = 0x55;public static final int EXT_NEG= 0x56;public static final int COMMON_EXT_NEG = 0x57;public static final int RQ_USER_IDENTITY = 0x58;public static final int AC_USER_IDENTITY = 0x59;}只做第一个我,不做第二个谁。

dicom(mDCM)中的UserIdentity字段

相关文章:

你感兴趣的文章:

标签云: