基于dcmtk cmove scu仅供参考
#ifndef DICOMCMOVESCU_H
#define DICOMCMOVESCU_H
#include "dcmtk/config/osconfig.h"
#include "dcmtk/ofstd/ofcond.h" /* for class OFCondition */
#include "dcmtk/dcmdata/dcxfer.h" /* for E_TransferSyntax */
#include "dcmtk/dcmnet/dimse.h" /* for T_DIMSE_BlockingMode */
#include <string>
class DcmDataset;
class DcmTransportLayer;
class OFConsoleApplication;
struct T_ASC_Association;
struct T_ASC_Parameters;
struct T_DIMSE_C_FindRQ;
struct T_DIMSE_C_FindRSP;
class CListCtrl;
struct tag_Movekey
{
std::string studydate;
std::string studytime;
std::string paitientId;
std::string paitientname;
std::string accessionNumber;
std::string birthdate;
std::string studyid;
std::string studyInstanceUid;
std::string refphName;
std::string sericeNumber;
std::string sericeUid;
std::string instanceNumber;
std::string instanceUid;
std::string reqId;
std::string ppsid;
std::string studyinMod;
std::string sericeMod;
std::string ppsdate;
std::string ppstime;
std::string ql;
long dw;
CListCtrl *listctr;
//net
std::string aet_;
std::string ip_;
int port_;
std::string aeted_;
bool secureConnection;
unsigned short maxReceivePDULength;
unsigned short acse_timeout;
OFBool mopt_abortAssociation;
std::string mopt_moveDestination;
std::string sopClass;
//回调指针
tag_Movekey()
{
maxReceivePDULength=16383;
secureConnection=false;
acse_timeout=10;
mopt_abortAssociation = OFFalse;
sopClass=UID_MOVEPatientRootQueryRetrieveInformationModel;
//UID_MOVEStudyRootQueryRetrieveInformationModel
}
};
class DicomCMoveScu
{
public:
DicomCMoveScu();
~DicomCMoveScu();
public:
bool startMove();
void move();
OFCondition addPresentationContext(
T_ASC_Parameters *params,
const char *abstractSyntax,
E_TransferSyntax preferredTransferSyntax);
void SetParamter(tag_Movekey &movekey_);
private:
T_ASC_Network *net_;
tag_Movekey moveKey_;
T_DIMSE_BlockingMode mopt_blockMode;
};
#endif
#include "winsock2.h"
#include "stdafx.h"
#include "DicomCMoveScu.h"
#include "dcmtk/config/osconfig.h"
#include "dcmtk/ofstd/ofstdinc.h"
#include "dcmtk/ofstd/ofstd.h"
#include "dcmtk/ofstd/ofconapp.h"
#include "dcmtk/dcmnet/dicom.h"
#include "dcmtk/dcmnet/dimse.h"
#include "dcmtk/dcmnet/diutil.h"
#include "dcmtk/dcmdata/dcfilefo.h"
#include "dcmtk/dcmdata/dcuid.h"
#include "dcmtk/dcmdata/dcdict.h"
#include "dcmtk/dcmdata/cmdlnarg.h"
#include "dcmtk/dcmdata/dcdeftag.h"
#include "dcmtk/dcmdata/dcmetinf.h"
#include "dcmtk/dcmdata/dcuid.h"
#include "dcmtk/dcmdata/dcdicent.h"
#include "dcmtk/dcmdata/dcostrmz.h"
#include "../pacslog.h"
typedef struct {
T_ASC_Association *assoc;
T_ASC_PresentationContextID presId;
long mopt_cancelAfterNResponses ;
bool IsCancelNResponses;
tag_Movekey *mokey;
} MyCallbackInfo;
static void
moveCallback(void *callbackData, T_DIMSE_C_MoveRQ *request,
int responseCount, T_DIMSE_C_MoveRSP *response)
{
OFCondition cond = EC_Normal;
MyCallbackInfo *myCallbackData;
myCallbackData = OFstatic_cast(MyCallbackInfo*, callbackData);
CString text;
text.Format(_T("%d"),responseCount);
myCallbackData->mokey->listctr->SetItemText(myCallbackData->mokey->dw-1,10,text);
OFString temp_str;
DICOM_INFO("Move Response " << responseCount << ":" << OFendl << DIMSE_dumpMessage(temp_str, *response, DIMSE_INCOMING));
/* should we send a cancel back ?? */
if (myCallbackData->IsCancelNResponses&&myCallbackData->mopt_cancelAfterNResponses == responseCount) {
DICOM_INFO("Sending Cancel Request: MsgID " << request->MessageID
<< ", PresID " << myCallbackData->presId);
cond = DIMSE_sendCancelRequest(myCallbackData->assoc,
myCallbackData->presId, request->MessageID);
if (cond != EC_Normal) {
DICOM_ERROR("Cancel Request Failed: " << DimseCondition::dump(temp_str, cond));
}
}
}
DicomCMoveScu::DicomCMoveScu()
:net_(0),
mopt_blockMode(DIMSE_BLOCKING)
{
}
DicomCMoveScu::~DicomCMoveScu()
{
}
void DicomCMoveScu::SetParamter(tag_Movekey &movekey)
{
moveKey_=movekey;
}
OFCondition DicomCMoveScu::addPresentationContext(
T_ASC_Parameters *params,
const char *abstractSyntax,
E_TransferSyntax preferredTransferSyntax)
{
const char* transferSyntaxes[] = { NULL, NULL, NULL, NULL };
int numTransferSyntaxes = 0;
switch (preferredTransferSyntax) {
case EXS_LittleEndianImplicit:
transferSyntaxes[0] = UID_LittleEndianImplicitTransferSyntax;
numTransferSyntaxes = 1;
break;
case EXS_LittleEndianExplicit:
transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax;
transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax;
transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax;
numTransferSyntaxes = 3;
break;
case EXS_BigEndianExplicit:
transferSyntaxes[0] = UID_BigEndianExplicitTransferSyntax;
transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax;
transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax;
numTransferSyntaxes = 3;
break;
default:
if (gLocalByteOrder == EBO_LittleEndian) /* defined in dcxfer.h */
{
transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax;
transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax;
} else {
transferSyntaxes[0] = UID_BigEndianExplicitTransferSyntax;
transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax;
}
transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax;
numTransferSyntaxes = 3;
break;
}
return ASC_addPresentationContext(
params, 1, abstractSyntax,
transferSyntaxes, numTransferSyntaxes);
}
bool DicomCMoveScu::startMove()
{
OFString temp_str;
T_ASC_Parameters *params = NULL;
const char *opt_peer=moveKey_.ip_.c_str();
OFCmdUnsignedInt opt_port =moveKey_.port_;
DIC_NODENAME localHost;
DIC_NODENAME peerHost;
T_ASC_Association *assoc = NULL;
const char *opt_peerTitle =moveKey_.aeted_.c_str();
const char *opt_ourTitle =moveKey_.aet_.c_str();
if (!dcmDataDict.isDictionaryLoaded())
{
DICOM_INFO("no data dictionary loaded, check environment variable: "
<< DCM_DICT_ENVIRONMENT_VARIABLE);
}
//1 初始化网络
OFCondition cond = ASC_initializeNetwork(NET_REQUESTOR, 0, moveKey_.acse_timeout, &net_);
if (cond.bad())
{
DICOM_FATAL("cannot create network: " << DimseCondition::dump(temp_str, cond));
return false;
}
//2 创建参数
cond = ASC_createAssociationParameters(¶ms, moveKey_.acse_timeout);
if (cond.bad()) {
DICOM_FATAL(DimseCondition::dump(temp_str, cond));
return false;
}
//设置ae
ASC_setAPTitles(params, opt_ourTitle, opt_peerTitle, NULL);
gethostname(localHost, sizeof(localHost) - 1);
sprintf(peerHost, "%s:%d", opt_peer, OFstatic_cast(int, opt_port));
//设置演示地址
ASC_setPresentationAddresses(params, localHost, peerHost);
//添加演示上下文
cond = addPresentationContext(params, moveKey_.sopClass.c_str(),
EXS_LittleEndianExplicit);
if (cond.bad()) {
DICOM_FATAL(DimseCondition::dump(temp_str, cond));
return false;
}
DICOM_DEBUG("Request Parameters:" << OFendl << ASC_dumpParameters(temp_str, params, ASC_ASSOC_RQ));
DICOM_INFO("请求关联");
cond = ASC_requestAssociation(net_, params, &assoc);
if (cond.bad()) {
if (cond == DUL_ASSOCIATIONREJECTED) {
T_ASC_RejectParameters rej;
ASC_getRejectParameters(params, &rej);
DICOM_FATAL("Association Rejected:");
DICOM_FATAL(ASC_printRejectParameters(temp_str, &rej));
return false;
} else {
DICOM_FATAL("Association Request Failed:");
DICOM_FATAL( DimseCondition::dump(temp_str, cond));
return false;
}
}
DICOM_DEBUG("Association Parameters Negotiated:" << OFendl << ASC_dumpParameters(temp_str, params, ASC_ASSOC_AC));
if (ASC_countAcceptedPresentationContexts(params) == 0) {
DICOM_FATAL("No Acceptable Presentation Contexts");
return false;
}
DICOM_INFO("Association Accepted (Max Send PDV: " << assoc->sendPDVLength << ")");
cond = EC_Normal;
T_ASC_PresentationContextID presId;
T_DIMSE_C_MoveRQ req;
T_DIMSE_C_MoveRSP rsp;
DIC_US msgId = assoc->nextMsgID++;
DcmDataset *rspIds = NULL;
const char *sopClass;
DcmDataset *statusDetail = NULL;
MyCallbackInfo callbackData;
presId = ASC_findAcceptedPresentationContextID(assoc, moveKey_.sopClass.c_str());
if (presId == 0) return false;
DICOM_INFO("Sending Move Request: MsgID " << msgId);
callbackData.assoc = assoc;
callbackData.presId = presId;
callbackData.IsCancelNResponses=false;
callbackData.mokey=&moveKey_;
req.MessageID = msgId;
strcpy(req.AffectedSOPClassUID, moveKey_.sopClass.c_str());
req.Priority = DIMSE_PRIORITY_MEDIUM;
req.DataSetType = DIMSE_DATASET_PRESENT;
if (moveKey_.mopt_moveDestination.empty()) {
ASC_getAPTitles(assoc->params, req.MoveDestination,
NULL, NULL);
} else {
strcpy(req.MoveDestination, moveKey_.mopt_moveDestination.c_str());
}
DcmDataset dest;
dest.putAndInsertString(DCM_QueryRetrieveLevel,moveKey_.ql.c_str());
dest.putAndInsertString(DCM_StudyInstanceUID,moveKey_.studyInstanceUid.c_str());
DICOM_INFO("移动条件:" << OFendl << DcmObject::PrintHelper(dest));
cond = DIMSE_moveUser(assoc, presId, &req, &dest,
moveCallback, &callbackData, mopt_blockMode, moveKey_.acse_timeout, net_, 0,
NULL, &rsp, &statusDetail, &rspIds, OFTrue);
if (cond==EC_Normal) {
OFString temp_str;
DICOM_INFO(DIMSE_dumpMessage(temp_str, rsp, DIMSE_INCOMING));
if (rspIds != NULL) {
DICOM_INFO("Response Identifiers:" << OFendl << DcmObject::PrintHelper(*rspIds));
}
} else {
OFString temp_str;
DICOM_ERROR("Move Request Failed: " << DimseCondition::dump(temp_str, cond));
}
if (statusDetail != NULL) {
DICOM_WARN("Status Detail:" << OFendl << DcmObject::PrintHelper(*statusDetail));
delete statusDetail;
}
if (rspIds != NULL) delete rspIds;
if (cond == EC_Normal)
{
if (moveKey_.mopt_abortAssociation) {
DICOM_INFO("Aborting Association");
cond = ASC_abortAssociation(assoc);
if (cond.bad()) {
DICOM_FATAL("Association Abort Failed: " << DimseCondition::dump(temp_str, cond));
return false;
}
} else {
DICOM_INFO("Releasing Association");
cond = ASC_releaseAssociation(assoc);
if (cond.bad())
{
DICOM_FATAL("Association Release Failed:");
DICOM_FATAL( DimseCondition::dump(temp_str, cond));
return false;
}
}
}
else if (cond == DUL_PEERREQUESTEDRELEASE)
{
DICOM_ERROR("Protocol Error: Peer requested release (Aborting)");
DICOM_INFO("Aborting Association");
cond = ASC_abortAssociation(assoc);
if (cond.bad()) {
DICOM_FATAL("Association Abort Failed: " << DimseCondition::dump(temp_str, cond));
return false;
}
}
else if (cond == DUL_PEERABORTEDASSOCIATION)
{
DICOM_INFO("Peer Aborted Association");
}
else
{
DICOM_ERROR( "Move SCU Failed: " << DimseCondition::dump(temp_str, cond));
DICOM_INFO("Aborting Association");
cond = ASC_abortAssociation(assoc);
if (cond.bad()) {
DICOM_FATAL("Association Abort Failed: " << DimseCondition::dump(temp_str, cond));
return false;
}
}
cond = ASC_destroyAssociation(&assoc);
if (cond.bad()) {
DICOM_FATAL(DimseCondition::dump(temp_str, cond));
return false;
}
cond = ASC_dropNetwork(&net_);
if (cond.bad()) {
DICOM_FATAL(DimseCondition::dump(temp_str, cond));
return false;
}
return false;
}
void DicomCMoveScu::move()
{
startMove();
delete this;
}
DICOM协议交流群:107534874