从 JAVA 程序使用 dcm4che 连接到 dcm4chee

Connecting to dcm4chee using dcm4che from a JAVA program

更新

我深入研究了 dcm4che 的源代码,发现 IncompatibleConnectionException 如果

我不知道连接是什么意思 "installed" 但这个标志可以手动设置,所以我将它设置为本地和远程连接 true (甚至选中他们 getInstalled() 他们是否 "installed" - 是的他们现在 - 以前这个 属性 是 null).

至于协议,它们没有指定,所以对于两个连接,我都将它们设置为 DICOM

结果:我仍然得到相同的异常。


我想在 dcm4chee (2.18.3) and my JAVA application using the dcm4che (5.12.0) 工具包之间建立 DICOM 关联。

问题是它似乎没有任何关于如何在 JAVA 应用程序中使用 dcm4che 的文档,所以我所能做的就是阅读 dcm4che 的源代码并尝试弄清楚它是什么类 和方法适用,但我卡住了。如果有人已经有一个工作示例,那将非常有帮助。

到目前为止我有:

import org.dcm4che3.net.ApplicationEntity;
import org.dcm4che3.net.Association;
import org.dcm4che3.net.Connection;
import org.dcm4che3.net.Device;
import org.dcm4che3.net.pdu.AAssociateRQ;
import org.dcm4che3.net.pdu.PresentationContext;

...

ApplicationEntity locAE = new ApplicationEntity();
locAE.setAETitle("THIS_JAVA_APP");

Connection localConn = new Connection();
localConn.setCommonName("loc_conn");
localConn.setHostname("localhost");
localConn.setPort(11112);
localConn.setProtocol(Connection.Protocol.DICOM);
localConn.setInstalled(true);
locAE.addConnection(localConn);

ApplicationEntity remAE = new ApplicationEntity();
remAE.setAETitle("DCM4CHEE");

Connection remoteConn = new Connection();
remoteConn.setCommonName("rem_conn");
remoteConn.setHostname("localhost");
remoteConn.setPort(11112);
remoteConn.setProtocol(Connection.Protocol.DICOM);
remoteConn.setInstalled(true);
remAE.addConnection(remoteConn);

AAssociateRQ assocReq = new AAssociateRQ();
assocReq.setCalledAET(remAE.getAETitle());
assocReq.setCallingAET(locAE.getAETitle());
assocReq.setApplicationContext("1.2.840.10008.3.1.1.1");
assocReq.setImplClassUID("1.2.40.0.13.1.3");
assocReq.setImplVersionName("dcm4che-5.12.0");
assocReq.setMaxPDULength(16384);
assocReq.setMaxOpsInvoked(0);
assocReq.setMaxOpsPerformed(0);
assocReq.addPresentationContext(new PresentationContext(
    1, "1.2.840.10008.1.1", "1.2.840.10008.1.2"));

Device device = new Device("device");
device.addConnection(localConn);
device.addApplicationEntity(locAE);

Association assoc = locAE.connect(remAE, assocReq);

但我不知道自己是否走在正确的道路上。

我得到的错误:

org.dcm4che3.net.IncompatibleConnectionException: No compatible connection to DCM4CHEE available on THIS_JAVA_APP
at org.dcm4che3.net.ApplicationEntity.findCompatibelConnection(ApplicationEntity.java:646)
at org.dcm4che3.net.ApplicationEntity.connect(ApplicationEntity.java:651)

可能是您的设置中缺少一个 Device 实例?看来,您需要一个 Device,您将 ApplicationEntityConnection.

附加到它上面

查看来自 dcm4che 源的 FindSCU.java 源。

private final Device device = new Device("findscu");
private final ApplicationEntity ae = new ApplicationEntity("FINDSCU");
private final Connection conn = new Connection();

public FindSCU() throws IOException {
    device.addConnection(conn);
    device.addApplicationEntity(ae);
    ae.addConnection(conn);
}

我还认为,也许本地 Connection 对象可以在没有任何参数的情况下实例化,如 FindSCU 示例所示。也许参数以某种方式混淆了它,特别是考虑到您有指向 localhost:11112.

的本地和远程连接

但是,必须承认,dcm4che3 API 的文档完全不够。

这是工作代码:(我不知道它是否是最小的解决方案,请随意尝试...)

ApplicationEntity locAE = new ApplicationEntity();
locAE.setAETitle("THIS_JAVA_APP");
locAE.setInstalled(true);

Connection localConn = new Connection();
localConn.setCommonName("loc_conn");
localConn.setHostname("localhost");
localConn.setPort(11112);
localConn.setProtocol(Connection.Protocol.DICOM);
localConn.setInstalled(true);
locAE.addConnection(localConn);

ApplicationEntity remAE = new ApplicationEntity();
remAE.setAETitle("DCM4CHEE");
remAE.setInstalled(true);

Connection remoteConn = new Connection();
remoteConn.setCommonName("rem_conn");
remoteConn.setHostname("localhost");
remoteConn.setPort(11112);
remoteConn.setProtocol(Connection.Protocol.DICOM);
remoteConn.setInstalled(true);
remAE.addConnection(remoteConn);

AAssociateRQ assocReq = new AAssociateRQ();
assocReq.setCalledAET(remAE.getAETitle());
assocReq.setCallingAET(locAE.getAETitle());
assocReq.setApplicationContext("1.2.840.10008.3.1.1.1");
assocReq.setImplClassUID("1.2.40.0.13.1.3");
assocReq.setImplVersionName("dcm4che-5.12.0");
assocReq.setMaxPDULength(16384);
assocReq.setMaxOpsInvoked(0);
assocReq.setMaxOpsPerformed(0);
assocReq.addPresentationContext(new PresentationContext(
    1, "1.2.840.10008.1.1", "1.2.840.10008.1.2"));

Device device = new Device("device");
device.addConnection(localConn);
device.addApplicationEntity(locAE);

Executor exec = (Runnable command) -> {};
device.setExecutor(exec);

Association assoc = locAE.connect(localConn, remoteConn, assocReq);

以及相关的 dcm4chee 日志:

2018-03-02 23:21:42,832 INFO  THIS_JAVA_APP->DCM4CHEE (TCPServer-1) [org.dcm4cheri.net.FsmImpl] received AAssociateRQ
    appCtxName: 1.2.840.10008.3.1.1.1/DICOM Application Context Name
    implClass:  1.2.40.0.13.1.3
    implVersion:    dcm4che-5.12.0
    calledAET:  DCM4CHEE
    callingAET: THIS_JAVA_APP
    maxPDULen:  16378
    asyncOpsWindow: 
    pc-1:   as=1.2.840.10008.1.1/Verification SOP Class
        ts=1.2.840.10008.1.2/Implicit VR Little Endian
2018-03-02 23:21:42,843 INFO  THIS_JAVA_APP->DCM4CHEE (TCPServer-1) [org.dcm4cheri.net.FsmImpl] sending AAssociateAC
    appCtxName: 1.2.840.10008.3.1.1.1/DICOM Application Context Name
    implClass:  1.2.40.0.13.1.1.1
    implVersion:    dcm4che-1.4.34
    calledAET:  DCM4CHEE
    callingAET: THIS_JAVA_APP
    maxPDULen:  16352
    asyncOpsWindow: 
    pc-1:   0 - acceptance
        ts=1.2.840.10008.1.2/Implicit VR Little Endian

有了关联后,see this other post如何执行C-FIND。

编辑

看来,我解决了这个问题。从

更改执行者
Executor exec = (Runnable command) -> {};
device.setExecutor(exec);

ExecutorService executorService = Executors.newSingleThreadExecutor();
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
device.setExecutor(executorService);
device.setScheduledExecutor(scheduledExecutorService);

使我的应用程序正确地接收到来自服务器的关联响应。这可以作为其他人的参考。

感谢您分享您的代码。对我很有帮助。

原版Post

我无法使用类似于您提出的解决方案的代码执行连接。我正在尝试请求与 dcm4chee-arc-light 和 dcm4che(均为 5.14.1)的关联,我有如下:

Device device = new Device(deviceName);
ApplicationEntity locAE = new ApplicationEntity(localAE);
Connection conn = new Connection();
Connection remote = new Connection();
AAssociateRQ rq = new AAssociateRQ();

device.addConnection(conn);
device.addApplicationEntity(locAE);
locAE.addConnection(conn);

ApplicationEntity remAE = new ApplicationEntity();
remAE.setAETitle(remoteAE);

remote.setCommonName("rem_conn");
remote.setHostname(remoteIP);
remote.setPort(remotePort);
remote.setProtocol(Connection.Protocol.DICOM);
remAE.addConnection(remote);

rq.setCalledAET(remAE.getAETitle());
rq.setCallingAET(locAE.getAETitle());
rq.setApplicationContext("1.2.840.10008.3.1.1.1");
rq.setImplClassUID("1.2.40.0.13.1.3");
rq.setImplVersionName("dcm4che-5.14.1");
rq.setMaxPDULength(16384);
rq.setMaxOpsInvoked(0);
rq.setMaxOpsPerformed(0);
rq.addPresentationContext(new PresentationContext(
        1, "1.2.840.10008.5.1.4.1.2.2.1", "1.2.840.10008.1.2"));

Executor exec = (Runnable command) -> {};
device.setExecutor(exec);

//Opens association and connects to remote server
Association as = locAE.connect(conn, remote, rq);

但是当尝试连接到远程 AET 时,它似乎没有收到来自远程 AET 的 AAssociation 响应。我的 Java 应用程序在 Sta5 中挂起(等待关联响应),而服务器在 Sta6 中挂起(准备好进行数据传输)。

Java 日志:

[main] INFO org.dcm4che3.net.Connection  - Initiate connection from 0.0.0.0/0.0.0.0:0 to localhost:11112
[main] INFO org.dcm4che3.net.Connection  - Established connection Socket[addr=localhost/127.0.0.1,port=11112,localport=50101]
[main] DEBUG org.dcm4che3.net.Association  - /127.0.0.1:50101>localhost/127.0.0.1:11112(1): enter state: Sta4 - Awaiting transport connection opening to complete
[main] INFO org.dcm4che3.net.Association  - DEVICEAE->DCMQRSCP(1) << A-ASSOCIATE-RQ
[main] DEBUG org.dcm4che3.net.Association  - A-ASSOCIATE-RQ[
  calledAET: DCMQRSCP
  callingAET: DEVICEAE
  applicationContext: 1.2.840.10008.3.1.1.1 - DICOM Application Context Name
  implClassUID: 1.2.40.0.13.1.3
  implVersionName: dcm4che-5.14.1
  maxPDULength: 16378
  maxOpsInvoked/maxOpsPerformed: 1/1
  PresentationContext[id: 1
  as: 1.2.840.10008.5.1.4.1.2.2.1 - Study Root Query/Retrieve Information Model - FIND
  ts: 1.2.840.10008.1.2 - Implicit VR Little Endian
 ]
]
[main] DEBUG org.dcm4che3.net.Association  - DEVICEAE->DCMQRSCP(1): enter state: Sta5 - Awaiting A-ASSOCIATE-AC or A-ASSOCIATE-RJ PDU

服务器日志:

19:11:29,397 INFO  - Accept connection Socket[addr=/127.0.0.1,port=50101,localport=11112]
19:11:29,397 DEBUG - /127.0.0.1:11112<-/127.0.0.1:50101(3): enter state: Sta2 - Transport connection open
19:11:29,416 INFO  - DCMQRSCP<-DEVICEAE(3) >> A-ASSOCIATE-RQ
19:11:29,416 DEBUG - A-ASSOCIATE-RQ[
 calledAET: DCMQRSCP
 callingAET: DEVICEAE
 applicationContext: 1.2.840.10008.3.1.1.1 - DICOM Application Context Name
 implClassUID: 1.2.40.0.13.1.3
 implVersionName: dcm4che-5.14.1
 maxPDULength: 16378
 maxOpsInvoked/maxOpsPerformed: 1/1
 PresentationContext[id: 1
 as: 1.2.840.10008.5.1.4.1.2.2.1 - Study Root Query/Retrieve Information Model - FIND
 ts: 1.2.840.10008.1.2 - Implicit VR Little Endian
  ]
 ]
19:11:29,419 DEBUG - DCMQRSCP<-DEVICEAE(3): enter state: Sta3 - Awaiting local A-ASSOCIATE response primitive
19:11:29,419 INFO  - DCMQRSCP<-DEVICEAE(3) << A-ASSOCIATE-AC
19:11:29,419 DEBUG - A-ASSOCIATE-AC[
 calledAET: DCMQRSCP
 callingAET: DEVICEAE
 applicationContext: 1.2.840.10008.3.1.1.1 - DICOM Application Context Name
 implClassUID: 1.2.40.0.13.1.3
 implVersionName: dcm4che-5.14.1
 maxPDULength: 16378
 maxOpsInvoked/maxOpsPerformed: 1/1
 PresentationContext[id: 1
 result: 0 - acceptance
 ts: 1.2.840.10008.1.2 - Implicit VR Little Endian
  ]
 ]
19:11:29,427 DEBUG - DCMQRSCP<-DEVICEAE(3): enter state: Sta6 - Association established and ready for data transfer

感觉好像少了点什么,但是找不到问题的根源。感谢您的帮助,因为我对 dcm4che 和 DICOM 协议还很陌生。

谢谢。