ConquestDICOMServer:DICOM测试环境搭建与C-STORE/C-FIND实战指南

发布时间:2026/9/3 17:50:14
ConquestDICOMServer:DICOM测试环境搭建与C-STORE/C-FIND实战指南 简介Conquest DICOM Server 是一款用于医疗影像系统联调与测试的开源 DICOM SCP 服务器工具面向 HIS/RIS 实施工程师、医疗软件开发者及系统管理员可模拟 DICOM 设备接收和响应请求帮助验证 PACS 集成、工作列表Worklist查询及网络通信是否正常。压缩包约 22.28MB内含 10 个主要文件覆盖核心可执行程序 ConquestDICOMServer.exe、DgateServ.exe、CqDicom.dll 动态库以及 .bat 启动/安装脚本、DICOM 字典文件、匿名化脚本和 7-Zip 命令行工具等便于在本地快速搭建测试环境并处理影像收发、数据匿名化与日志监控。已有 710 人浏览学习。借助该工具开发者可低成本完成 DICOM SCP/SCU 兼容性测试、系统性能评估和跨 PACS 数据迁移演练有效排查通信异常并保障医疗影像数据在传输与存储中的合规安全。 手里攒了一批CT、MR的DICOM文件需要验证自己写的PACS客户端能不能正常收发或者刚搭好一套归档系统想确认C-STORE、C-FIND这些服务到底通不通。这种时候手动开个软件去发图、点半天界面查图效率实在太低。我一般直接甩一个轻量的DICOM服务器到测试环境里用脚本和命令行工具来回打——这套东西里ConquestDICOMServer是我用得最顺手的一个测试工具。ConquestDICOMServer是一个开源、单机可跑的DICOM服务器支持Windows、Linux、macOS核心就一个几百KB的进程装上以后可以当作迷你PACS用。它原生支持DICOM C-STORE存储、C-FIND查询、C-MOVE拉取、C-GET直接取、MPPS、Query/Retrieve这些常用服务还能接SQLite、MySQL、PostgreSQL存储索引。写DICOM应用的开发者拿它当测试靶子医院信息科拿它做离线阅片归档硬件厂商拿它验证设备输出——三个场景我都干过。这篇文章就围绕ConquestDICOMServer把我在测试环境里从安装到对接的完整操作理一遍包括选型原因、配置参数、常见坑和处理思路偏向DICOM开发者和运维人员视角如果你是刚接触DICOM协议测试的新人这套流程可以直接照抄。1. 为什么测试DICOM服务我会选Conquest而不是其他方案1.1 测试DICOM应用的几个典型场景DICOM服务端的测试说起来无非是三四件事第一类是验证自己写的SCU能正常把图发给服务端。你写了个C-STORE SCU要给影像归档发图服务端得能正确收图、返回成功状态最好还能把收到的文件落盘方便回读校验。第二类是验证自己写的SCP能正常收图。你写了个简易存档服务需要用一个客户端源源不断发来多模态数据验证并发、大文件、序列完整性。没有现成SCP做对象测试就得自己造。第三类是验证Query/Retrieve链路。客户端按患者、检查、序列查询服务端拿到结果列表后再发起C-MOVE或者C-GET把图拉回来。这要求服务端有完整的数据索引和检索能力。第四类是验证设备或系统的DICOM连通性。比如新到一台超声机医院要让它能往PACS发图那就得先有个兼容的DICOM服务端做联调等接口确认了再接入生产PACS。这些场景下可以选的工具不少DCMTK的storedsmpr可以当简易SCPOrthanc也能做服务端还有像dcm4chee这类重型的。但要么是功能单一不好扩展要么是配置文件太厚要么是部署起来要数据库、要应用服务器测试环节根本不想碰这么重的依赖。1.2 Conquest的优势与取舍ConquestDICOMServer在这个定位里属于“小而全”的代表。它的优势非常明显部署极轻Windows解压即用Linux下编译或直接跑二进制几乎零依赖。一个进程全搞定不需要容器化不需要装额外服务。协议支持全C-STORE、C-FIND、C-MOVE、C-GET、MPPS、Modality Worklist这些都是原生支持的对测试来讲已经覆盖了90%的日常需求。数据库可选纯文件模式索引直接存文件可以零数据库启动适合快速验证要测试大批量数据时切成SQLite或者MySQL索引检索效率会好很多。配置集中所有配置都在一个dicom.ini里改起来直观不需要翻GUI点半天。当然它也有缺点界面是真的简陋基本没有现代化Web管理端日志也偏原始高并发场景下性能不如Orthanc这类为服务端场景优化的项目部分新DICOM标准扩展比如DICOMweb不支持。但测试场景里这些缺点影响不大——要的是快速起一个服务端能收到图、能查到记录、能配合流程验证。总结生产级归档系统我不会用Conquest但测试环境里我不会再绕开它。是那种能一直留在工具箱里的实用工具。2. 测试环境搭建安装与初始配置2.1 安装与启动以Linux环境为例我从源码编译的方式比较稳。Conquest代码仓库提供了Unix Makefile依赖其实只有libpng、libjpeg、libssl和sqlite的开发包。Ubuntu/Debian下先把这些装上sudo apt-get install -y build-essential libpng-dev libjpeg-dev libssl-dev libsqlite3-dev git clone https://github.com/innolitics/dicom3tools.git git clone https://github.com/vincent/sftp.git注意不对ConquestDICOMServer的源码仓库是单独的官方原版在SourceForge上GitHub上有一些镜像。我一般不自己编译直接用发行版或者官方编译好的二进制省时间。如果非要源码构建核心步骤是git clone https://github.com/winfsp/dicomserver.git # 或者从SourceForge拉 cd dicomserver make linux ./dgate --version编译完启动./dgate如果看到类似Conquest DICOM Server, Version 1.5.0的输出说明起来了。默认监听端口是5678这是Conquest编译期写死的默认端口可以后面在dicom.ini里改。Windows下更简单下载官方Windows安装包解压后直接双击dgate.exe服务默认作为控制台程序跑起来。要装成系统服务官方包里带了install_service.bat脚本。2.2 初始配置dicom.ini核心参数Conquest所有配置在dicom.ini里位置和编译时的配置路径有关常见的是程序同目录或者/etc/dicomserver。先看几个最关键的# 服务端AE Title AETitle CONQUESTSVR # TCP监听端口 TCPPort 5678 # 存储路径收到的文件都会放这里 RootPath /var/lib/dicomserver/data # 使用的数据库类型支持 file, sqlite, mysql, postgres等 Database sqlite # 数据库连接信息sqlite模式下是文件路径 SQLitePath /var/lib/dicomserver/data/dicom.db # 最大PDU大小越大传输大文件越省事65536是个安全值 MaxPDUSize 65536 # 允许的peer对端最大PDU测试时可以设大点 MaxPDUPeer 65536 # 是否启用压缩传输0不启用1启用 Compression 0几个容易忽略的点RootPath这个目录是Conquest存储DICOM文件的实际位置。在文件数据库模式下它会把收到的dcm文件按序列/实例打散存成一个复杂目录树。测试时如果你想快速找到刚发过来的原始文件直接在这里面按时间sort是找不到的它有自己的一套目录规则用dgate --scan或者数据库查询反而方便。AETitle这是Conquest和外部通信的身份标识任何客户端发起关联请求时请求的Called AE Title必须和这里一致否则关联会被拒绝。DICOM测试里大量“连接不上”“Unknown AE Title”的报错90%是这个字段没对齐。MaxPDUSizePDUProtocol Data Unit是DICOM传输层的数据包。如果两端的PDU大小不匹配就按小的那个走。测试时把Conquest设成65536客户端用4096也能正常通信但是网络利用率会差传大的增强CT序列时会明显慢。改完配置重启dgate然后看日志确认配置生效。日志默认打到控制台重定向到文件更方便./dgate /var/log/conquest/dgate.log 21 2.3 验证服务端存活配置完了先自测一下最简单的办法是拿DCMTK里的工具去ping一下。DCMTK里的echoscu是标准DICOM C-ECHO验证关联客户端用法echoscu -aet TESTSCU -aec CONQUESTSVR 127.0.0.1 5678返回类似Requesting Association... Association Accepted (Maximum PDU: 16384) Sending Echo Request... Received Echo Response (Success) Releasing Association...只要看到Association Accepted和Echo Response (Success)说明Conquest服务端关联、C-ECHO服务都是通的接下来可以正式测试。这一步我每次都会做不是效率问题而是后续所有问题排查都需要先确认“底层链路通不通”。有个干净基线后面出问题才不至于来回猜。3. 核心测试能力拆解从C-STORE到Query/Retrieve3.1 C-STORE数据上送与接收测试C-STORE是最常用的DICOM操作对应“把图发过去”。测试时用DCMTK的storescu作为SCUConquest作为SCPstorescu -aet SCUTEST -aec CONQUESTSVR 127.0.0.1 5678 /path/to/ct_001.dcm一个大坑Conquest对非标准DICOM文件兼容性远不如Orthanc那样严格。比如有些厂商导出的dcm文件头不完整或者Transfer Syntax不对Conquest常常收下以后直接拒绝建立索引表现为“收了文件但查询列表里没有记录”。我遇到一次某型号的乳腺机导出的DICOM文件MetaHeader里TransferSyntax写的是1.2.840.10008.1.2.1Explicit VR Little Endian但实际数据是压缩过的storescu发送时其实没报错Conquest也给了Success状态结果查询时发现图像缺失。这种情况其实是发送端没有把文件正确转码不是Conquest的问题。建议发送端统一先预处理成规范的Explicit Little Endian或JPEG无损格式再发。批量发送多组文件时storescu可以一次传多个路径storescu -aet SCUTEST -aec CONQUESTSVR 127.0.0.1 5678 /data/patient1/*.dcm /data/patient2/*.dcmC-STORE测完之后检查三件事服务端返回状态每个文件会返回对应状态码0000代表成功其他如A700out of resources、0122SOP Class not supported都要排查。文件是否落盘去RootPath下的目录确认有没有新增dcm文件。数据库是否建立索引用SQLite查询确认patient/study/series/instance四个层级都建好了sqlite3 /var/lib/dicomserver/data/dicom.db SELECT * FROM DICOMStudies;3.2 C-FIND查询服务验证C-FIND是客户端向服务端发起查询服务端返回匹配记录。Conquest的C-FIND响应逻辑严格按Patient Root Query/Retrieve Information Model实现所以查询键的层级要符合DICOM标准。DCMTK的findscu支持通过query文件指定查询条件# find_query.dcm (0010,0010) PN PatientName TEST* (0008,0020) DA StudyDate (0020,000D) UI StudyInstanceUID 保存成dcm格式然后执行findscu -aet SCUTEST -aec CONQUESTSVR 127.0.0.1 5678 -q -f find_query.dcm或者直接命令行写查询条件但比较复杂我更喜欢query文件。测试C-FIND时几个典型场景按患者姓名模糊查询测试PatientName通配符匹配逻辑。按检查日期范围查询测试StudyDate的区间条件。按StudyInstanceUID精确查询测试唯一键检索——只返回一条记录。C-FIND最容易踩的坑是QueryRetrieveLevel填错导致的空结果。比如明明是Study级查询但把SOPInstanceUID属于Image级塞进了查询键Conquest会返回空。level的对应关系QueryRetrieveLevel查询键示例返回层级PATIENTPatientID, PatientName患者STUDYStudyInstanceUID, StudyDate检查SERIESSeriesInstanceUID, Modality序列IMAGESOPInstanceUID图像实例3.3 C-MOVE和C-GET拉取数据验证C-MOVE是两个服务端之间转存的操作客户端自己不接收数据而是指示源服务端把数据发给另一个服务端。测试时客户端就是“调度者”。DCMTK的movescu用法movescu -aet SCUTEST -aec CONQUESTSVR 127.0.0.1 5678 -aem TARGETAE -k QueryRetrieveLevelSTUDY -k StudyInstanceUID1.2.840.113619.2.55.3.2831169228.682关键参数-aem指定目标AE Title。这里一定要保证Conquest的dicom.ini里定义了TARGETAE这个对端否则它会报Unknown AE Title并拒绝发送。TARGETAE对应的主机和端口可达且那台机器上得有监听中的DICOM服务。在dicom.ini中对端配置格式[TARGETAE] Host 192.168.1.100 Port 11112 AETitle TARGETAEC-GET和C-MOVE的区别是C-GET由SCP直接把数据发给SCU不经过中间服务端操作逻辑更直接。Conquest对C-GET的支持也不错测试时可以用getscugetscu -aet SCUTEST -aec CONQUESTSVR 127.0.0.1 5678 -k QueryRetrieveLevelSERIES -k SeriesInstanceUID1.2.840.113619.2.55.3.2831169228.682.1C-MOVE和C-GET的测试常用来验证网络传输、多跳场景以及验证对端SCP是否能正确处理接收。3.4 多模态与并发测试Conquest作为测试靶子还常被用来做并发压力验证。比如同时开3个storescu往同一个AE Title发图验证Conquest的并发处理能力。实测下来Conquest多线程接受C-STORE请求的能力很稳但并发写入数据库索引时容易出现锁冲突日志里偶尔能看到database is locked的SQLite报错。要改善并发写入换MySQL/PostgreSQLSQLite在写并发高时锁等待明显换数据库后缓解很多。调大MaxSimultaneousAssociations默认好像是4还是8测试时可以调大。确认日志路径没有挤爆磁盘调测并发时日志量很大不清理的话磁盘会满。4. 常见问题与排查技巧实录4.1 关联失败Association Rejected最常见的问题症状是客户端报Requesting Association... Association Rejected: Result: 2, Source: 1, Reason: 1原因基本就三类Called AE Title不对客户端设置的Called AE-aec参数和Conquest的AETitle不一致。检查dicom.ini里的AETitle或者客户端参数拼写。端口不通Conquest监听端口写错或者防火墙挡了。用netstat -tlnp | grep 5678确认监听nc -zv 127.0.0.1 5678测连通。对端AE没注册Conquest默认对未知的Calling AE会直接拒绝RequireCalledAETitle之类的配置。可以在dicom.ini里加[SSSCU] Host * Port 0 AETitle *这样允许任意AE接入但生产不要这么配只限于本机测试。4.2 能发送成功但文件找不见storescu返回Success但数据库查不到记录。排查思路看日志Conquest日志会打印每次关联、存储的明细有没有报“Ignored”或者“Failed to store file”。看RootPath如果文件在目录下存在但数据库没有大概率是数据库写入失败关注SQLite锁错误。看SOP Class如StoredPrint打印对象、Encapsulated PDF这类非图像SOP ClassConquest的默认配置可能不处理。需要在[SSSCU]下的SOPClass里显式启用。4.3 C-FIND查到数据但C-MOVE拉不回来这个坑也很典型。C-FIND能找到Study但发C-MOVE时报“Cannot Understand”或者“No Such Object Instance”。最常犯的错误是C-MOVE的查询键层级和C-FIND混用。C-FIND可以用StudyDate这种通用键但C-MOVE对QueryRetrieveLevelSTUDY而言核心检索键实际是StudyInstanceUID和PatientID。把C-FIND的返回结果完整保留再作为C-MOVE的输入键一般不会错。还有一个冷门坑Conquest在文件数据库模式下如果数据文件的路径损坏比如手动改过RootPath目录C-FIND能读到数据库索引但C-MOVE去读文件时找不到对应实体会报“File Not Found”。这种情况要去检查RootPath和数据库记录的路径一致性。4.4 日志定位技巧Conquest日志级别可以通过dicom.ini的LogLevel字段调整从0到3越高越详细。实际排查问题时我常直接调到2结合系统级抓包工具对比两端的DICOM消息。配合wireshark在dcm4che和Conquest之间的这条链路上看关联请求、P-DATA的流转能定位绝大多数协议层问题。搭建测试环境时留好一个常驻终端的日志窗口能让你少走很多弯路。4.5 常见问题速查表症状可能原因检查/处理Association RejectedAE Title不匹配、端口不通、对端未注册核对AETitle、TCPPort、dicom.ini对端条目发送成功但查询无记录数据库写入失败/文件未正常解析看日志、检查SQLite锁、确认SOPClass支持C-MOVE返回Cannot Understand查询键层级不对/文件缺失核对QueryRetrieveLevel与查询键确认RootPath完整日志刷磁盘LogLevel过高/并发测试量大调低日志级别、定期切割日志Windows下服务启动失败端口被占/权限不足netstat查端口、管理员权限启动5. 扩展玩法自动化测试与数据回写5.1 把Conquest接入自动化测试脚本测试环境不只有人工点击我更习惯把它和脚本绑定。比如用Python的pydicom先造一个最小DICOM测试文件包含必填标签再用子进程调用storescu发给Conquest再查数据库验证记录。整个链路可以在CI里跑import pydicom from pydicom.dataset import Dataset from pydicom.uid import generate_uid ds Dataset() ds.PatientName AutoTest^Patient ds.PatientID PID-0001 ds.StudyInstanceUID generate_uid() ds.SeriesInstanceUID generate_uid() ds.SOPInstanceUID generate_uid() ds.Modality CT ds.SOPClassUID 1.2.840.10008.5.1.4.1.1.2 ds.file_meta pydicom.dataset.FileMetaDataset() ds.file_meta.MediaStorageSOPClassUID ds.SOPClassUID ds.file_meta.MediaStorageSOPInstanceUID ds.SOPInstanceUID ds.file_meta.TransferSyntaxUID 1.2.840.10008.1.2.1 ds.is_little_endian True ds.is_implicit_VR False ds.save_as(test_ct.dcm, write_like_originalFalse)然后在同一个脚本里用subprocess调用storescu再用sqlite3库去读Conquest的索引库确认新增记录。这一套可以完全无人值守。5.2 作为Worklist模拟器Conquest还集成了**Modality WorklistMWL**服务这个在生产环境的设备联调中特别实用。CT、MR机器要向RIS系统拉取预约检查列表开发时没有真实的RIS就可以用Conquest模拟MWL SCP。配置Worklist的SOP Class然后在数据库里插入Worklist条目patient、scheduled procedure等设备端用MWL C-FIND就能查到。这在验证设备“预约接收”流程时非常有用。不过Conquest的Worklist功能相对简陋只具备基础查询不保证对复杂排班逻辑的支持。要真实模拟复杂排班规则建议用专用的模拟器比如DCM4CHE的MWL工具但Conquest作为轻量的入门版是够了。5.3 数据回写与迁移Conquest里的dicom文件也能往外迁移。用C-MOVE把数据从Conquest拉到另一个PACS或者直接把RootPath里的文件用脚本转出来。要注意DICOM文件的SOPInstanceUID和数据库记录必须一致直接拷文件到另一个系统会丢失索引所以建议走标准的C-MOVE或C-GET流程。6. 竞品对比什么场景选Orthanc什么场景选Conquest可能你会问现在Orthanc也很流行为什么不直接用Orthanc我实际两个都用过做个简单的对比特性ConquestDICOMServerOrthanc部署复杂度和资源占用极低单进程较低但需要多进程和Web服务REST API基本没有非常完善主流方案DICOMweb不支持原生支持数据库file/sqlite/mysql/postgresqlSQLite或PostgreSQL高并发/大数据量一般更好管理界面简陋自带Web UI直观协议扩展传统DICOM全套更现代支持更广适合场景轻量测试、临时靶子、快速联调服务平台、持续集成的服务端底座简单说Conquest是“轻量靶子”Orthanc是“服务底座”。测试一个人写的小工具发一批数据验证逻辑用Conquest足够但要做一套自动化集成测试的常驻服务天天被脚本调来调去还需要Web API去查数据、删数据那Orthanc的REST API会让你省心很多。我的建议是测试机和持续集成环境里可以两个都装一个专门模拟“传统设备级SCP”一个用来处理需要动态管理数据的自动化链路。反正两个都是开源工具不冲突。7. 测试DICOM工具链的完整落地建议最后把整个Conquest测试环境的搭建变成一套“可复制”的流程单独准备一台测试机或者虚拟机不建议和开发环境混跑DICOM测试会产生大量镜像文件磁盘用量增长很快。装好Conquest并跑通C-ECHO这是基线一切测试都从它开始。准备一批标准的测试DICOM文件至少包含CT、MR、XA各一份Transfer Syntax尽量覆盖无压缩和JPEG无损。来源可以从公开数据集下载比如TCIA。配置好对端AE只加测试专有AE不想逐个加就配通配AE。写一套自动化脚本C-STORE、C-FIND、C-MOVE、C-GET各一例作为回归测试用例每次代码改动后跑一遍。定期清理数据conquest数据库文件积攒得很快测试数据不清理到后期会拖慢查询脚本定期删库重建即可。按这几个步骤做下来以后再接到“帮测一下DICOM服务”的请求基本能在一个小时内给出一个可靠的结果。测试的目的不是把环境搭得有多豪华而是快速、可重复地验证问题。ConquestDICOMServer就是那种不起眼、但能在关键时候替你省下一整晚的测试基础设施。本文还有配套的精品资源点击获取