DICOM协议下 C#实现 CFind CMove的SCU简单例子
FO-DICOM 实现C-Find + C-Move 客户端SCU 文件传输例子
学习过程中理解到关于 CFind 、CMove 的一些业务逻辑说明 以及实现代码(复制粘贴即可使用),不讲解底层原理,大佬请无视
近期在项目需求有用到 CFind CMove 这两种方式一起的文件传输模式 (老实说觉得挺麻烦的),但该做还是要做的。 因为是第一次接触这种通信方式的项目,看了些网络相关资料,并不复杂,但多数对新人不是很友好 没有相关经验的理解起来比较困难,磕磕绊绊 总算是搞明白了,这里做下记录。
- C-Find 释义:可以想象成一个数据查询接口 提交对应查询条件(这个要看服务端查询的实现情况,服务端不支持的条件 加了也没用) 服务端返回给你对应的检查数据集合 (这里以StudyInstanceUID 为返回结果为例) 例子:
static string pacsIp = "127.0.0.1";///测试的服务IP static int pacsPort = 5678;///测试的服务端口 static string localAe = "YUANTK";///本地的AE static string remoteAe = "CONQUEST";///服务的AE ///查询10天内的Study数据(前提是服务器那边支持) DicomDateRange SearchDateRange= new DicomDateRange(DateTime.Now.AddDays(-10), DateTime.Now); DicomClient client = new DicomClient(pacsIp, pacsPort, false, localAe, remoteAe); //var cfind = DicomCFindRequest.CreateStudyQuery(null,null,SearchDateRange);//调用演示例子 //由于本次测试的服务端并不支持时间范围查询 所以我这里测试没用加这个条件 var cfind = DicomCFindRequest.CreateStudyQuery(); ///C-Find绑定结果回调事件 接收服务器返回的结果 cfind.OnResponseReceived = (rq, res) => { Console.WriteLine("cfind 请求完成"); string StudyInstuceUID = res.Dataset?.GetSingleValueOrDefault<string>(DicomTag.StudyInstanceUID, ""); if (res.Status==Dicom.Network.DicomStatus.Success) { Console.WriteLine("C-Find查询结束"); return; } //到这里就可以拿到返回StudyInstuceUID 为后续的C-Move 做准备 Console.WriteLine($"CFind 返回StudyInstuceUID :{StudyInstuceUID} "); }; ///添加请求 client.AddRequestAsync(cfind).Wait(); ///发送请求 client.SendAsync().Wait();
- C-Move 释义:就是发送一个指定StudyInstuceUID查询的然后 服务器会将查询结果以CStore的方式发送到指定的SCP收图服务 例子:
DicomClient CMoveClient = new DicomClient(pacsIp, pacsPort, false, localAe, remoteAe); ///理解这里耗费了学习过程的大部分时间 string TargetAe="CStoreSCP";//注意 这个是服务端配置的 请求成功后 服务会往对应的节点发送CStore文件请求 ///创建CMove请求 指定对应的TargetAe 以及需要目标 StudyInstuceUID DicomCMoveRequest CMoveRequest = new DicomCMoveRequest(TargetAe, StudyInstuceUID, Dicom.Network.DicomPriority.Medium); ///CMove绑定结果回调事件 接收服务器返回的结果 CMoveRequest.OnResponseReceived += (Dicom.Network.DicomCMoveRequest rq1, Dicom.Network.DicomCMoveResponse rs) => { //成功后pacs会往指定的AE(TargetAe)发送CStore文件请求 if (rs.Status == Dicom.Network.DicomStatus.Success) { Console.WriteLine("CMove 请求完成"); return; } }; ///添加请求 CMoveClient.AddRequestAsync(CMoveRequest).Wait(); ///发送请求 CMoveClient.SendAsync().Wait();
说明:由于Fo-DICOM 的开源库 使用 版本不一样,可能会出现代码不完全一样的情况。
本文测试使用的模拟服务器软件是 CONQUEST 有兴趣的可以去官网下载一个做模拟测试