Java DICOM 网络传输_DICOM医学图像处理:fo-dicom网络传输之 C-Echo and C-Store
背景:
上一篇博文對(duì)DICOM中的網(wǎng)絡(luò)傳輸進(jìn)行了介紹,主要參照DCMTK Wiki中的英文原文。通過(guò)對(duì)比DCMTK與fo-dicom兩個(gè)開(kāi)源庫(kù)對(duì)DICOM標(biāo)準(zhǔn)的具體實(shí)現(xiàn),對(duì)理解DICOM標(biāo)準(zhǔn)有一個(gè)更直觀的認(rèn)識(shí)。此篇博文是對(duì)上一篇博文的補(bǔ)充,因?yàn)閷谇懊娴氖纠蠖嗍抢肈CMTK工具包來(lái)進(jìn)行的,此次借著分析fo-dicom源碼結(jié)構(gòu)的機(jī)會(huì),參照f(shuō)o-dicom的README.md,給出C-ECHO 和C-STORE服務(wù)的具體實(shí)現(xiàn)。在實(shí)現(xiàn)的同時(shí)給出DICOM3.0標(biāo)準(zhǔn)中的相關(guān)介紹,幫助我們理解。
C-ECHO的fo-dicom實(shí)現(xiàn):
1)C-ECHO參數(shù)說(shuō)明:
C-ECHO又叫驗(yàn)證服務(wù)(即Verification),是用來(lái)驗(yàn)證DICOM服務(wù)兩端的交流是否暢通。DICOM3.0的第7部分給出了C-ECHO服務(wù)的參數(shù),如下圖1所示:
【注意】:這里講解一下DICOM3.0標(biāo)準(zhǔn)的閱讀方法。以DICOM3.0標(biāo)準(zhǔn)的第7、8部分為例,【第7部分】中第9章開(kāi)始講解DIMSE-C的各種服務(wù),依次為C-STORE、C-FIND、C-GET、C-MOVE、C-ECHO(上圖1就是我在該部分的C-ECHO小節(jié)中截取的),其中前半部分主要給出了DIMSE-C各種服務(wù)的參數(shù),這里僅僅是羅列出DICOM3.0標(biāo)準(zhǔn)的要求,目的是讓你明白各個(gè)服務(wù)參數(shù)是否是必要的(分別用M、U、=表示);后半部分開(kāi)始講解DIMSE-C各種服務(wù)的協(xié)議及實(shí)現(xiàn)流程(即Protocol和Procedures),在PROTOCOL中給出的是具體的DIMSE-C服務(wù)的各種指令在傳輸過(guò)程中的格式,該部分也就是你利用抓包工具能夠直接抓取的真實(shí)數(shù)據(jù)流;在Procedures中給出的是SCU和SCP之間的交互流程,通常為了說(shuō)明服務(wù)是由誰(shuí)發(fā)起的,由誰(shuí)響應(yīng)。在介紹Protocol的時(shí)候?qū)τ诒容^復(fù)雜的、可變的區(qū)域(Variables Fields)通常會(huì)放在附錄中,例如第7部分的附錄C和E等;【第8部分】與【第7部分】類似,從第7章開(kāi)始介紹ACSE的各種服務(wù)的參數(shù)(如下圖2所示),依次為A-ASSOCIATE、A-RELEASE、A-ABORT、A-P-ABORT、P-DATA;第9章給出的是ACSE中各種服務(wù)的結(jié)構(gòu),即STRUCTURE,該部分與【第7部分】中的PROTOCOL相同,給出的是具體ACSE PDU在傳輸時(shí)刻的數(shù)據(jù)格式,該部分也是可以通過(guò)抓包工具直接獲得的;同樣對(duì)于比較復(fù)雜的STRUCTURE介紹也會(huì)單獨(dú)放到附錄中,例如第8部分的附錄E。
fo-dicom對(duì)于DIMSE消息的實(shí)現(xiàn)基類是DicomMessage,針對(duì)請(qǐng)求和響應(yīng)分別派生出了DicomRequest和DicomResponse,最后根據(jù)不同的DIMSE服務(wù)派生相應(yīng)的類。C-ECHO是其中最簡(jiǎn)單的,fo-dicom已經(jīng)給出了SCP和SCU的具體實(shí)現(xiàn)。參照f(shuō)o-dicom中的README.md文件,給出C-ECHO SCP和SCU的代碼,詳情如下:
2)C-ECHO代碼實(shí)例:
C-ECHO SCP的代碼是直接利用了fo-dicom給出的DicomCEchoProvider類,通過(guò)創(chuàng)建DicomServer(12345)對(duì)象,開(kāi)啟C-ECHO SCP服務(wù),其中參數(shù)12345表示C-ECHO服務(wù)的端口號(hào)。C-ECHO SCU和C-ECHO SCP的代碼分別如下所示:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Dicom;
using Dicom.Network;
namespace CEchoSCU
{
class Program
{
static void Main(string[] args)
{
var client = new DicomClient();
client.NegotiateAsyncOps();
client.AddRequest(new DicomCEchoRequest());
client.Send("127.0.0.1", 12345, false, "SCU", "ANY-SCP");
Console.ReadLine();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using Dicom;
using Dicom.Network;
namespace CEchoSCP
{
class Program
{
static void Main(string[] args)
{
var server = new DicomServer(12345);
Console.ReadLine();
}
}
}
實(shí)際運(yùn)行結(jié)果如下:
C-STORE的fo-dicom實(shí)現(xiàn):
1)C-STORE參數(shù)說(shuō)明:
C-STORE就是存儲(chǔ)服務(wù),在醫(yī)療信息系統(tǒng)中最常見(jiàn)的服務(wù)之一,尤其是PACS系統(tǒng)中。與C-ECHO服務(wù)相同,DICOM3.0標(biāo)準(zhǔn)第7部分也給出了C-STORE服務(wù)的參數(shù)列表,如下圖4所示:
該參數(shù)列表的目的同樣是為了介紹C-STORE服務(wù)中各參數(shù)的必要性,真正的參數(shù)消息格式在后續(xù)的C-STORE PROTOCOL中介紹,如下圖5所示:
圖5中給出的僅僅是C-STORE RQ的實(shí)際消息格式,該消息由C-STORE服務(wù)的SCU(客戶端)流向C-SOTRE服務(wù)的SCP(服務(wù)端);與之相對(duì)應(yīng)的C-STORE-RSP消息是從SCP流向SCU,DICOM3.0標(biāo)準(zhǔn)中也有C-STORE-RSP的詳細(xì)介紹,如下圖6所示。
2)C-STORE代碼實(shí)例:
在fo-dicom的說(shuō)明文檔README.md中只給出了C-STORE的SCU示例,如下圖7所示:
上一篇博文對(duì)fo-dicom源碼結(jié)構(gòu)分析的基礎(chǔ)上可知,實(shí)現(xiàn)DIMSE眾多服務(wù)的SCU端很容易,首先創(chuàng)建DicomClient實(shí)體類,代表一個(gè)客戶端,然后通過(guò)AddRequest添加不同的請(qǐng)求即可實(shí)現(xiàn)各種DIMSE的客戶端,如圖7中C-STORE SCU的實(shí)現(xiàn)為:
client.AddRequest(new DicomCStoreRequest(@"test.dcm"));
DicomCStoreRequest類是DicomRequest的派生類,上述代碼通過(guò)制定DCM文件路徑來(lái)構(gòu)建了一個(gè)DicomCStoreRequest對(duì)象,在DicomCStoreRequest內(nèi)部通過(guò)打開(kāi)指定的DCM文件提取獲得上述參數(shù)中的Affected SOP Instance UID等參數(shù)。
既然fo-dicom中沒(méi)有提供線程的C-STORE SCP實(shí)現(xiàn),我們先利用DCMTK的storescp.exe工具來(lái)驗(yàn)證一下fo-dicom給出的C-STORE SCU的正確性,測(cè)試代碼如下:
SCP端利用storescp.exe,在控制臺(tái)下輸入:storescp.exe –d –od c:\ 12345
SCU端利用fo-dicom中的C-STORE SCU,具體代碼如上圖7所示,然后雙擊生成后的storescu.exe。
最后可以得到如下結(jié)果,如圖8所示:
同時(shí)在C盤根目錄下可以看到被重命名的test.dcm文件,如下圖9所示:
之所以被重命名我們?cè)谥胺治鯠CMTK開(kāi)源庫(kù)源碼時(shí)提到過(guò),通常DCMTK會(huì)根據(jù)SOP Instance UID(-uf,默認(rèn)的)對(duì)接收到的DCM文件進(jìn)行重命名,當(dāng)然也可以通過(guò)選項(xiàng)設(shè)置重命名的方式,例如按照時(shí)間(-tn)、特定前綴(-fe)等等,如下圖10所示。
由此說(shuō)明fo-dicom中給出的C-STORE SCU功能正常,接下來(lái)我們嘗試?yán)胒o-dicom構(gòu)建C-STORE SCP。
3)構(gòu)建C-STORE SCP
打開(kāi)C-ECHO SCP的實(shí)現(xiàn)DicomCEchoProvider.cs文件,我們看到DicomCEchoProvider類通過(guò)派生DicomService服務(wù)類來(lái)實(shí)現(xiàn)了Dicom服務(wù)的基本框架,然后通過(guò)實(shí)現(xiàn)IDicomServiceProvider和IDicomCEchoProvider接口,完成了C-ECHO 的服務(wù)端,仔細(xì)查看DicomCEchoProvider的代碼可以發(fā)現(xiàn),其實(shí)就是在接收到A-ASSOCIATE-RQ消息后,判別Presentation Context中的Abstract Syntax,根據(jù)實(shí)際請(qǐng)求消息來(lái)決定是否建立連接,另外當(dāng)接收到C-ECHO SCU發(fā)起的C-ECHO Request時(shí),向其會(huì)送DicomCEchoResponse確認(rèn)信息即可。
既然通過(guò)實(shí)現(xiàn)兩個(gè)接口函數(shù)就可以完成C-ECHO SCP的構(gòu)建,那么我們就自己嘗試來(lái)完成C-STORE SCP的搭建,仿照DicomCEchoProvider的方式,DicomCStoreProvider的代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dicom;
using Dicom.Log;
using Dicom.Network;
using System.Threading;
using System.IO;
namespace CStoreSCP
{
class CStoreSCPProvider : DicomService, IDicomServiceProvider, IDicomCStoreProvider
{
public CStoreSCPProvider(Stream stream, Logger log) : base(stream, log) { }
public DicomCStoreResponse OnCStoreRequest(DicomCStoreRequest request)
{
return new DicomCStoreResponse(request,DicomStatus.Success);
}
public void OnCStoreRequestException(string tempFileName, Exception e)
{
}
public void OnReceiveAssociationRequest(DicomAssociation association)
{
foreach (var pc in association.PresentationContexts)
{
if (pc.AbstractSyntax == DicomUID.Verification)
pc.SetResult(DicomPresentationContextResult.Accept);
else
{
//pc.SetResult(DicomPresentationContextResult.RejectAbstractSyntaxNotSupported);
}
if (pc.AbstractSyntax == DicomUID.CTImageStorage)
{
pc.SetResult(DicomPresentationContextResult.Accept);
}
}
SendAssociationAccept(association);
}
public void OnReceiveAssociationReleaseRequest()
{
SendAssociationReleaseResponse();
}
public void OnReceiveAbort(DicomAbortSource source, DicomAbortReason reason)
{
}
public void OnConnectionClosed(int errorCode)
{
}
}
}
然后通過(guò)var server = new DicomServer(12345);Console.ReadLine(); 來(lái)構(gòu)建一個(gè)C-STORE SCP應(yīng)用。
下圖11是先運(yùn)行CStoreSCP.exe,然后運(yùn)行CStoreSCU.exe得到的結(jié)果:
從圖11的輸出結(jié)果可以看出,此次C-STORE SCP和SCU兩端的通訊順利完成,那么我們發(fā)送的C:\test.dcm文件會(huì)被CStoreSCP.exe存儲(chǔ)到那里呢?由上一篇博文分析我們知道fo-dicom庫(kù)中將DICOM的服務(wù)基本框架放在了DicomService類中,查看其中處理P-DATA服務(wù)的核心函數(shù)ProcessPDataTF,可以看到如下代碼:
var file = new DicomFile();
file.FileMetaInfo.MediaStorageSOPClassUID = pc.AbstractSyntax;
file.FileMetaInfo.MediaStorageSOPInstanceUID = _dimse.Command.Get(DicomTag.AffectedSOPInstanceUID);
file.FileMetaInfo.TransferSyntax = pc.AcceptedTransferSyntax;
file.FileMetaInfo.ImplementationClassUID = Association.RemoteImplemetationClassUID;
file.FileMetaInfo.ImplementationVersionName = Association.RemoteImplementationVersion;
file.FileMetaInfo.SourceApplicationEntityTitle = Association.CallingAE;
_dimseStream = CreateCStoreReceiveStream(file);
轉(zhuǎn)到CreateCStoreReceiveStream函數(shù)內(nèi)部,通過(guò)函數(shù)的說(shuō)明就可以知道fo-dicom對(duì)C-STORE服務(wù)默認(rèn)情況下是在系統(tǒng)中創(chuàng)建了一個(gè)臨時(shí)文件,用來(lái)接收C-STORE SCU的數(shù)據(jù),因此可以推斷我們的test.dcm文件應(yīng)該也在臨時(shí)文件夾中,打開(kāi)我本機(jī)的temp文件夾,可以看到有一個(gè)后綴為tmp的臨時(shí)文件,如下圖12所示。文件大小與我們測(cè)試用的test.dcm相同,嘗試修改.tmp的擴(kuò)展名,修改后可以使用DICOM Viewer軟件正常打開(kāi),因此說(shuō)明我們的C-STORE SCP順利成功。
DICOM數(shù)據(jù)流分析:
C-ECHO服務(wù)數(shù)據(jù)流分析:
1)工具:
在本地測(cè)試,為了抓取127.0.0.1回路數(shù)據(jù)包,需要使用RawCap.exe工具包。RawCap.exe是控制臺(tái)程序,在抓取本地回路數(shù)據(jù)包時(shí)很便捷。當(dāng)抓取完成后我們需要借助于WireShark的強(qiáng)大分析功能,來(lái)實(shí)現(xiàn)C-ECHO數(shù)據(jù)流的詳細(xì)分析,WireShark可以直接打開(kāi)RawCap.exe抓取的.pcap數(shù)據(jù)包。
WireShark是功能強(qiáng)大的數(shù)據(jù)包統(tǒng)計(jì)分析工具,當(dāng)然本身也可以抓取網(wǎng)絡(luò)數(shù)據(jù)包(本地回路數(shù)據(jù)包不方便)。WireShark支持眾多協(xié)議,其中包括DICOM協(xié)議。下面以C-ECHO的數(shù)據(jù)包為例,簡(jiǎn)單介紹一下如何使用WireShark來(lái)自動(dòng)識(shí)別并解析DICOM數(shù)據(jù)包。首先打開(kāi)抓取的本地C-ECHO數(shù)據(jù)包c(diǎn)echo.pcap。如圖13,在Protocol中右鍵選擇"Protocol Preferences “中的"Data Preferences…”,會(huì)彈出一個(gè)協(xié)議設(shè)置窗口如圖13。在左側(cè)列表中找到DICOM協(xié)議,勾選圖14中紅色部分。該部分的意思是除了檢測(cè)DICOM協(xié)議默認(rèn)端口104的數(shù)據(jù)包的同時(shí)也檢測(cè)其他端口的數(shù)據(jù)包。之所以需要選擇此項(xiàng)是因?yàn)楹芏郉ICOM服務(wù)并未使用協(xié)議默認(rèn)的104端口。設(shè)置完成后,重新查看Protocol列,可以看到出現(xiàn)了DICOM字樣,如圖15所示,最上方的帶DICOM字樣的數(shù)據(jù)包就是我們抓取到的C-ECHO服務(wù)的本地回路數(shù)據(jù)包。
2)C-ECHO數(shù)據(jù)流分析:
利用RawCap.exe和WireShark兩大強(qiáng)大的工具,我們已經(jīng)可以直觀的看到抓取的DICOM數(shù)據(jù)包了,接下來(lái)我就按照DICOM標(biāo)準(zhǔn)第7部分和第8部分中的內(nèi)容,逐個(gè)數(shù)據(jù)包來(lái)分析一下,通過(guò)觀察真實(shí)的數(shù)據(jù)包來(lái)加深一下對(duì)DICOM協(xié)議的理解。
從圖15中可以看到,最頂部DICOM協(xié)議包含6個(gè)數(shù)據(jù)包,分別是連接建立(A-ASSOCIATE RQ/A-ASSOCIATE AC)、數(shù)據(jù)交互(P-DATA-TF)、連接釋放(A-RELEASE RQ/A-RELEASE RP),這與DICOM協(xié)議第8部分中介紹的ACSE控制流程相符。
A-ASSOCIATE RQ/A-ASSOCATE AC分析:
雙擊第一個(gè)DICOM數(shù)據(jù)包,該數(shù)據(jù)包是A-ASSOCIATE RQ的真實(shí)數(shù)據(jù)流,如圖16所示:
按照DICOM協(xié)議第8部分中第9章對(duì)A-ASSOCIATE RQ PDU的描述,我們來(lái)逐項(xiàng)對(duì)比(DICOM協(xié)議可參照?qǐng)D17):第一項(xiàng)1個(gè)字節(jié)的PDU-type,圖中為01H,說(shuō)明該數(shù)據(jù)包代表的是A-ASSOCIATE RQ;第二項(xiàng)一個(gè)字節(jié)的保留,數(shù)據(jù)流為00H;第三項(xiàng)是四個(gè)字節(jié)的PDU-length,圖中為00 00 00 ff,轉(zhuǎn)換為無(wú)符號(hào)整數(shù)正好為255,這也是整個(gè)圖中藍(lán)色部分后續(xù)的數(shù)據(jù)包長(zhǎng)度;第四項(xiàng)是兩個(gè)字節(jié)的Protocol-Version,圖中為00 01,對(duì)應(yīng)版本為1;第五項(xiàng)為兩字節(jié)保留;第六項(xiàng)和第七項(xiàng)是我們熟悉的AE Title,從WireShark的數(shù)據(jù)流中也可以看出分別是ANY-SCP和ECHOSCU;第8項(xiàng)又是一堆保留字節(jié),用00H填充;第9項(xiàng)是一個(gè)可變區(qū)域(Variable Fields),該項(xiàng)是復(fù)合項(xiàng),內(nèi)部包含多個(gè)獨(dú)立的子項(xiàng)。由圖16可以看出該復(fù)合項(xiàng)內(nèi)部含有Application Context、Presentation Context(2個(gè),ID分別是1、3)、UserInfo三個(gè)子項(xiàng);而UserInfo又是一個(gè)復(fù)合項(xiàng),其內(nèi)部又包含了Max PDU Length、ImplentationUID、ImplentationVersion三個(gè)子項(xiàng)。從WireShark的分析來(lái)看,Application Context子項(xiàng)類型為10H、Presentation Context子項(xiàng)類型為20H、UserInfo子項(xiàng)為50H(其內(nèi)部的嵌套子項(xiàng)的類型分別為,Max PDU Length-51H、Implentation UID-52H、Implentation Version-55H)。各個(gè)子項(xiàng)的類型與DICOM協(xié)議第7、8兩部分中的附錄D相對(duì)應(yīng),例如圖19中我截取的是Max PDU Length子項(xiàng)的格式。A-ASSOCIATE AC的數(shù)據(jù)包分析與A-ASSOCIATE RQ類似,只是A-ASSOCIATE AC的數(shù)據(jù)流更簡(jiǎn)單一些,這里就不做詳細(xì)介紹了。(最終數(shù)據(jù)域DICOM協(xié)議的對(duì)應(yīng)結(jié)果如圖18)。
A-RELEASE RQ/A-RELEASE RP分析:
連接釋放的數(shù)據(jù)包格式簡(jiǎn)單,下面圖20和圖21分別是DICOM協(xié)議第8部分中給出的連接釋放請(qǐng)求和應(yīng)答數(shù)據(jù)包的格式:
雙擊WireShark中的連接釋放數(shù)據(jù)包,可以看到兩者的數(shù)據(jù)包類型分別為05H和06H,這與上圖中DICOM協(xié)議的規(guī)定完全一致。
P-DATA-TF:
在上一篇博文中(http://blog.csdn.net/zssureqh/article/details/41016091)我已經(jīng)分析了,DICOM協(xié)議第7部分中規(guī)定的DIMSE消息(Command和Dataset)是通過(guò)第8部分中ACSE協(xié)議中的P-DATA-TF服務(wù)以PDV的形式來(lái)傳輸?shù)摹O旅婢妥屛覀儊?lái)分析一下DIMSE消息中C-ECHO RQ 和C-ECHO RSP的格式:
雙擊WireShark數(shù)據(jù)包中間兩個(gè),從數(shù)據(jù)流向可以斷定一個(gè)是C-ECHO RQ消息,一個(gè)是C-ECHO RSP消息。先打開(kāi)第一個(gè),按照上一篇博文的分析,首先該數(shù)據(jù)包是一個(gè)P-DATA-TF PDU,因此需要符合下圖23中的格式。
通過(guò)分析最外層的是代表P-DATA-TF類型的04H,然后是由DIMSE消息填充的PDV區(qū)域,該項(xiàng)是復(fù)合項(xiàng),第一子項(xiàng)是Item-length,此處為46H;第二子項(xiàng)為Presentation-context-ID,此處為01H;第三子項(xiàng)又是一個(gè)復(fù)合項(xiàng),是DICOM標(biāo)準(zhǔn)第4部分中給出的DIMSE消息結(jié)構(gòu),包括Message Control Header、Command和DataSet三部分。此處的MessageControlHeader為03H,即表示是Command數(shù)據(jù)而不是DataSet,且是最后一個(gè)PDV,即Last Fragment。具體的對(duì)應(yīng)關(guān)系如圖24所示:
C-STORE服務(wù)數(shù)據(jù)流分析:
1)工具:
依然使用RawCap.exe+WireShark來(lái)解決。
2)C-STORE數(shù)據(jù)流分析:
按照C-ECHO中的分析方式,同樣可以看到DICOM數(shù)據(jù)包,如圖25所示:
A-ASSOCIATE RQ/A-ASSOCIATE AC:
對(duì)于A-ASSOCIATE RQ/A-ASSOCIATE AC的分析與C-ECHO中基本類似,唯一不同的就是對(duì)于C-STORE服務(wù)需要不同的Presentation Context描述上下文,如圖26所示,此處C-STORE需要的是CT Image Storage服務(wù),其SOP Class UID為1.2.840.10008.5.1.4.1.1.2。
A-RELEASE RQ/A-RELEASE RP:
與C-ECHO中的相同,這也說(shuō)明了博文中的C-ECHO 和C-STORE服務(wù)實(shí)現(xiàn)成功,連接能夠正常釋放。
P-DATA-TF:
此處著重分析一下C-STORE服務(wù)中的P-DATA-TF數(shù)據(jù)包,因?yàn)閭鬏斠粋€(gè)DCM文件需要多個(gè)PDU,自然也需要多個(gè)PDV。所以我們通過(guò)分析C-STORE的P-DATA-TF數(shù)據(jù)包可以更形象的學(xué)習(xí)Message Control Header和DIMSE的知識(shí)。
同樣傳輸?shù)拿總€(gè)數(shù)據(jù)包首先符合P-DATA-TF的格式要求,第一項(xiàng)是PDU類型,即04H;隨后是保留項(xiàng)、PDU-length、PDV復(fù)合項(xiàng)……,這與C-ECHO中的分析相同。按照上一篇博文的分析,C-STORE PROTOCOL的流程是CSTORE SCU向SCP發(fā)送C-STORE RQ消息,但是打開(kāi)圖中的第一個(gè)P-DATA數(shù)據(jù)包時(shí)我們看到的卻不是C-STORE RQ,而是其中的一個(gè)數(shù)據(jù)片段,如下圖27所示。
依次查看后面的幾個(gè)P-DATA數(shù)據(jù)包,都是類似的情況。最后倒數(shù)兩個(gè)分別是C-STORE RQ中DCM文件數(shù)據(jù)的最后一個(gè)數(shù)據(jù)包(Last Fragment)和SCP向SCU發(fā)送的C-STORE RSP,具體分析如圖28所示:
從最后數(shù)據(jù)包Command中的(0000,0100)的值域8001H可知該指令就是C-STORE RSP。
看到這里你或許會(huì)很興奮,因?yàn)槲覀兘K于也看到了C-STORE服務(wù)的真實(shí)數(shù)據(jù)流,但是在上圖中的所有DICOM對(duì)應(yīng)的數(shù)據(jù)包中我們并未找到C-STORE SCU發(fā)起的C-STORE RQ數(shù)據(jù)包,那么C-STORE RQ數(shù)據(jù)包在哪里呢?
讓我們將cstore.pcap的所有數(shù)據(jù)包按照時(shí)間排序,出現(xiàn)了大量標(biāo)記為[TCP segment of a reassembled PDU]的TCP數(shù)據(jù)包。
打開(kāi)第一個(gè)標(biāo)記為[TCP segment of a reassembled PDU]的TCP數(shù)據(jù)包,其內(nèi)部的真實(shí)數(shù)據(jù)分析如下圖30所示:
至此我們順利找到了C-STORE SCU端發(fā)送的C-STORE RQ消息,之所以沒(méi)有在WireShark中以DICOM協(xié)議顯示,可能是由于WireShark在識(shí)別多個(gè)連續(xù)分片的數(shù)據(jù)時(shí)不夠智能。博文中的示例圖和文字較多,仔細(xì)閱讀后應(yīng)該對(duì)DICOM3.0中的協(xié)議會(huì)有更進(jìn)一步的了解。通過(guò)分析數(shù)據(jù)包的方式在更直觀的學(xué)習(xí)和掌握DICOM3.0標(biāo)準(zhǔn)的同時(shí),對(duì)后期排查DICOM網(wǎng)絡(luò)傳輸相關(guān)錯(cuò)誤也會(huì)有幫助。
備注:
再次說(shuō)明一下閱讀DICOM3.0標(biāo)準(zhǔn)的方式:
以DICOM3.0標(biāo)準(zhǔn)的第7、8部分為例,【第7部分】中第9章開(kāi)始講解DIMSE-C的各種服務(wù),依次為C-STORE、C-FIND、C-GET、C-MOVE、C-ECHO(上圖1就是我在該部分的C-ECHO小節(jié)中截取的),其中前半部分主要給出了DIMSE-C各種服務(wù)的參數(shù),這里僅僅是羅列出DICOM3.0標(biāo)準(zhǔn)的要求,目的是讓你明白各個(gè)服務(wù)參數(shù)是否是必要的(分別用M、U、=表示);后半部分開(kāi)始講解DIMSE-C各種服務(wù)的協(xié)議及實(shí)現(xiàn)流程(即Protocol和Procedures),在PROTOCOL中給出的是具體的DIMSE-C服務(wù)的各種指令在傳輸過(guò)程中的格式,該部分也就是你利用抓包工具能夠直接抓取的真實(shí)數(shù)據(jù)流;在Procedures中給出的是SCU和SCP之間的交互流程,通常為了說(shuō)明服務(wù)是由誰(shuí)發(fā)起的,由誰(shuí)響應(yīng)。在介紹Protocol的時(shí)候?qū)τ诒容^復(fù)雜的、可變的區(qū)域(Variables Fields)通常會(huì)放在附錄中,例如第7部分的附錄C和E等;【第8部分】與【第7部分】類似,從第7章開(kāi)始介紹ACSE的各種服務(wù)的參數(shù)(如圖2所示),依次為A-ASSOCIATE、A-RELEASE、A-ABORT、A-P-ABORT、P-DATA;第9章給出的是ACSE中各種服務(wù)的結(jié)構(gòu),即STRUCTURE,該部分與【第7部分】中的PROTOCOL相同,給出的是具體ACSE PDU在傳輸時(shí)刻的數(shù)據(jù)格式,該部分也是可以通過(guò)抓包工具直接獲得的;同樣對(duì)于比較復(fù)雜的STRUCTURE介紹也會(huì)單獨(dú)放到附錄中,例如第8部分的附錄E。
實(shí)例工程及抓取的數(shù)據(jù)包:
后續(xù)專欄博文介紹:
利用PHP Skel結(jié)合DCMTK開(kāi)發(fā)WEB PACS應(yīng)用
利用oracle直接操作DICOM數(shù)據(jù)
C#的異步編程模式在fo-dicom中的應(yīng)用
VMWare三種網(wǎng)絡(luò)連接模式的實(shí)際測(cè)試
時(shí)間:2014-11-18
總結(jié)
以上是生活随笔為你收集整理的Java DICOM 网络传输_DICOM医学图像处理:fo-dicom网络传输之 C-Echo and C-Store的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java的character用法_Jav
- 下一篇: app上传头像处理Java_java后台