设为首页 加入收藏

TOP

DICOM医学图形处理:storescp.exe与storescu.exe源码剖析,学习C-STORE请求(续)(一)
2015-07-20 17:42:17 来源: 作者: 【 】 浏览:3
Tags:DICOM 医学 图形处理 storescp.exe storescu.exe 源码 剖析 学习 C-STORE 请求

背景:

上一篇博文中,在对storescp工具源文件storescp.cc和DcmSCP类的源文件scp.cc进行剖析后,得出了两者都可以实现响应C-ECHO和C-STORE(需要对DcmSCP类进行扩展)请求的功能。但是在对DcmSCP类进行扩展,期望模拟实现自己的storescp.exe工具时遇到了问题,客户端提示服务中断链接,而服务端显示保存失败,如下图所示。此次博文通过排除该问题再一次对storescp.cc和scp.cc进行对比,主要从Presentation Context、AbstractSyntax、TransferSyntax等细节出发,认真学习DICOM通讯服务。

\

问题排除:

1)对比分析storescp.exe工具包与自定义工具包的调试信息

为了排除storescu.exe客户端的问题,大致确定问题出现的范围,决定再一次用storescp.exe作为客户端,使用storescu.exe对其发送C-STORE请求,查看storescu.exe客户端的调试信息。与我们的自定义工具服务端的调试信息进行对比。

\

对比上图中的调试信息,其中红色部分END A-ASSOCIATE-AC表示的是服务端已经顺利的与客户端完成了握手,即网络已经顺利响应了客户端的连接。蓝色部分表示客户端发送的C-STORE-RQ请求也已经顺利的到达了服务端,唯一不同的就是黄色圆圈标记的部分,说明在服务端接收到C-STORE-RQ请求后对其处理有问题。而我们自己封装的ZSDcmStoreSCP类对于C-STORE-RQ的处理函数是直接拷贝的storescp.exe工具内的storeSCP和storeSCPCallback函数。因此大致可以确定问题可能出现的范围。

2)单步调试

在handleIncomingCommand函数内部调用storeSCP指令处插入断点,进入单步调试状态。利用VS2012提供的新的调试工具“并行堆栈”,找到了第一个返回状态cond.bad()为true的地方,即函数ASC_findAcceptedPresentationContext,如下图所示:

\

继续单步调试,进入到ASC_findAcceptedPresentationContext函数内部,发现真正出现错误的地方是findPresentationContextID,该函数的参数presentationContextID始终为零。

\

猜测:可能是presentationContextID参数在传递过程中的某一环节出错了,导致程序失败。为了验证我们的想法,打开storescp.exe工程,进入调试模式,查看参数的数值情况,如下图所示,storescp.exe工具包中presentationContextID参数的值为41。因此证明了我们在presentationContextID参数传递的过程中发生了错误。

\

3)参数传递流向

为了确定具体传递过程中的错误环节,我们采取回溯的方式,通过回溯findPresentationContextID函数中presentationContextID参数的来源来确定问题出现的具体位置。

\

(注:为了方便讲图片旋转了90度,劳烦大家歪着脖子将就着看一下下吧哈)

从上图中可以看出T_ASC_PresentationContextID参数最终的来源是我们重载DcmSCP基类的handleIncomingCommand函数,因此与storescp.exe中的是实现对比,仔细查看该部分的代码,发现了一个重大问题,原来我们在将storescp.exe工具中的processCommands函数内容拆解到handleIncomingCommand函数内部时,将多余的DIMSE_receiveCommand函数注释掉的同时,遗漏了注释掉T_ASC_Association局部变量,使得原本应该通过DIMSE_receiveCommand函数获取的presID变量一直被局部变量覆盖为0――至此问题找到了。

\

那么由于注释掉了多余的DIMSE_receiveCommand函数,我们从何处来获取presID参数呢。查看一下handleIncomingCommand函数的头发现函数参数中也没有出现T_ASC_PresentationContextID类型的参数。但是对比scp.cc原本处理C-ECHO请求的函数handleECHORequest我们发现,scp.cc类中将presID的值存储在了DcmPresentationContextInfo类型的presInfo变量中。因此我们修改storeSCP的调用,将presInfo.presentationContextID传递进入作为presID的初值。

\

修改完成后,再次调试发现程序运行正常,客户端顺利收到了服务端反馈回来的DIMSE Message,并且在服务端的目录下也看到了storescu.exe传递过来的dcm文件(当然在storeSCP函数内部根据时间等信息对文件进行了重命名)。

\

至此上一博文中自模拟storescp.exe工具包的问题已经顺利解决,利用我们自己封装的ZSDcmStoreSCP类可以简单地实现storescp.exe工具包的功能。

总结分析:

此次调试排除错误的过程中发现,在组合移接不同文件的代码时要格外的注意细节部分。顺便借着此次传递丢失T_ASC_Association类型参数的问题,我们详细的分析一下传递失败的T_ASC_Associaton类型参数的作用,为什么简单的一个参数传递失败,就会导致C-STORE功能失效?

1)Presentation Context、AbstractSyntax、TransferSyntax细节学习

在上一篇博文中我们摘录了DICOM3.0标准中关于Presentation Context、AbstractSyntax、TransferSyntax几个名词的解释,通俗一点来讲就是说Presentation Context代表的是两个应用实体(AE=Applicaiton Entity)交互的环境(通常叫做上下文),它包含后面的AbstractSyntax和TransferSyntax名词。AbstractSyntax与TransferSyntax比较容易混淆就是因为英文单词中都包含了Syntax,其实两者完全是不同的概念,AbstractSyntax关注的是上层信息,即两个交互的AE之间 进行的是何种交互,也就是标准中所说的服务对象对(SOP)的类型,通过查看dcuid.h文件可知,AbstractSyntax有Store、Query/Retrive、Worklist等类型,例如Store类型的UID_CTImageStorage 、Query/Retrive类型的UID_FINDPatientRootQueryRetrieveInformationModel、Worklist类型的UID_FINDModalityWorklistInformationModel等等。这几个是我们在C-ECHO、C-STORE、C-FIND

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇HDU4994-Revenge of Nim(博弈) 下一篇线性表 - 双链表

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·工业机器人TCP校准中 (2025-12-25 05:19:17)
·opc 通讯协议与 TCP (2025-12-25 05:19:15)
·labview中tcp/ip通信 (2025-12-25 05:19:13)
·新书介绍《Python数 (2025-12-25 04:49:47)
·怎么利用 Python 进 (2025-12-25 04:49:45)