LDicomNet::SendCEchoRequest

Summary

Sends a C-ECHO-REQ message to a peer member of a connection. This function is available in the PACS Imaging Toolkit.

Syntax

#include "ltdic.h"

L_INT LDicomNet::SendCEchoRequest(nPresentationID, nMessageID, pszClass)

Parameters

L_UCHAR nPresentationID

Presentation ID. The presentation ID provides information about both the class type of the data and the transfer syntax to use when transferring the data.

L_UINT16 nMessageID

Message ID. Each message sent by a member of a connection should have a unique ID. Since a member of a connection may send several messages, this ID allows that member to identify when a specific request has been completed.

L_TCHAR * pszClass

Class affected by the request. This will be an SOP Class or an SOP MetaClass.

Returns

Value Meaning
0 SUCCESS
>0 An error occurred. Refer to Return Codes.

Comments

Calling this function generates a call to LDicomNet::OnReceiveCEchoRequest on the SCP. The SCP should respond by calling LDicomNet::SendCEchoResponse which will generate a call to LDicomNet::OnReceiveCEchoResponse.

Required DLLs and Libraries

Platforms

Win32, x64

See Also

Functions

Topics

Example

This is a basic, but complete example that shows a DICOM client sending a C-Echo-REQ to a server, and the server processing the request.

namespace LDicomNet_SendCEchoRequest_Namespace 
{ 
   // Logs a message 
   // This implementation logs to the console, and the debug window 
   L_VOID LogMessage(TCHAR *szMsg) 
   { 
      wprintf(TEXT("\n")); 
      wprintf(szMsg); 
 
      OutputDebugStringW(TEXT("\n")); 
      OutputDebugStringW(szMsg); 
   } 
 
 
   // ******************************************************************************************* 
   // Client Class  
   // 
   // Class that is used to connect to the server  
   // ******************************************************************************************* 
   class CMyClient : public LDicomNet 
   { 
   public: 
      CMyClient(L_INT32 nMode): LDicomNet(NULL, nMode) 
      { 
         m_waitEvent = CreateEvent( NULL, TRUE, TRUE, TEXT("ClientEvent")); 
         ResetEvent(m_waitEvent); 
      } 
 
      ~CMyClient(void) 
      { 
         CloseHandle(m_waitEvent); 
      } 
 
      // Client 
      L_VOID OnConnect                    (L_INT nError); 
      L_VOID OnReceiveAssociateAccept     (LDicomAssociate *pPDU); 
      L_VOID OnReceiveReleaseResponse     (); 
      L_VOID OnReceiveCEchoResponse       (L_UCHAR nPresentationID, L_UINT16 nMessageID, L_TCHAR *pszClass, L_UINT16 nStatus); 
      L_VOID OnClose                      (L_INT nError, LDicomNet *pClient); 
 
      L_BOOL Wait(DWORD timeout = 5000); 
 
   private: 
      HANDLE m_waitEvent; 
   }; 
 
   // Continues dispatching messages until hEvent is signalled, our timeout 
   // Returns TRUE if hEvent is signalled 
   // Returns FALSE if timeout 
   L_BOOL MessageLoop ( 
      HANDLE hEvent, // handles that need to be waited on 
      DWORD timeout  // timeout in milliseconds 
      ) 
   { 
      DWORD dwStart = GetTickCount(); 
      MSG msg = {0}; 
 
      volatile L_BOOL bRunForever = TRUE; 
      while (bRunForever) 
      { 
         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))  
         { 
            TranslateMessage(&msg); 
            DispatchMessage(&msg); 
         } 
 
         if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0) 
         { 
            ResetEvent(hEvent); 
            return TRUE; 
         } 
 
         DWORD dwCurrent = GetTickCount(); 
         if ((dwCurrent - dwStart) > timeout) 
         { 
            return FALSE; 
         } 
      } 
      return TRUE; 
   } 
 
   L_VOID CMyClient::OnConnect(L_INT nError) 
   { 
      L_TCHAR szMsg[200] = {0}; 
 
      wsprintf(szMsg, TEXT("CMyClient::OnConnect: nError[%d]"), nError);  
      LogMessage(szMsg); 
   } 
 
   L_VOID CMyClient::OnReceiveAssociateAccept  (LDicomAssociate *pPDU) 
   { 
      UNREFERENCED_PARAMETER(pPDU); 
      SetEvent(m_waitEvent); 
      LogMessage(TEXT("CMyClient::OnReceiveAssociateAccept")); 
   } 
    
   L_VOID CMyClient::OnReceiveCEchoResponse(L_UCHAR nPresentationID, L_UINT16 nMessageID, L_TCHAR *pszClass, L_UINT16 nStatus) 
   { 
      SetEvent(m_waitEvent); 
      L_TCHAR szMsg[200] = {0}; 
 
      if (pszClass == NULL) 
      { 
         pszClass = TEXT(""); 
      } 
      wsprintf(szMsg, TEXT("CMyClient::OnReceiveCEchoResponse: \n\tnPresentationID[%d], \n\tnMessageID[%d], \n\tpszClass[%s], \n\tnStatus[%d]"), nPresentationID, nMessageID, pszClass, nStatus);  
      LogMessage(szMsg); 
   } 
 
   L_VOID CMyClient::OnReceiveReleaseResponse() 
   { 
      SetEvent(m_waitEvent); 
      LogMessage(TEXT("CMyClient::OnReceiveReleaseResponse")); 
   } 
    
   L_VOID CMyClient::OnClose(L_INT nError, LDicomNet *pClient) 
   { 
      UNREFERENCED_PARAMETER(nError); 
      UNREFERENCED_PARAMETER(pClient); 
      SetEvent(m_waitEvent); 
      LogMessage(TEXT("CMyClient::OnClose")); 
   } 
 
 
   L_BOOL CMyClient::Wait(DWORD timeout) 
   { 
      L_BOOL bRet = MessageLoop(m_waitEvent,  timeout);   
      return bRet; 
   } 
 
   // ******************************************************************************************* 
   // Server Connection Class  
   // 
   // When a client connects, CMyServer creates a new instance of the CMyServerConnection class  
   // and accepts the connection.   
   // ******************************************************************************************* 
   class CMyServerConnection : public LDicomNet 
   { 
   public: 
      CMyServerConnection(L_INT32 nMode): LDicomNet(NULL, nMode) 
      { 
      } 
      ~CMyServerConnection(void) 
      { 
      } 
 
      // Server 
      L_VOID OnReceiveAssociateRequest(LDicomAssociate *pPDU); 
      L_VOID OnReceiveAssociateReject(L_UCHAR nResult, L_UCHAR nSource, L_UCHAR nReason); 
      L_VOID OnReceiveCEchoRequest(L_UCHAR nPresentationID, L_UINT16 nMessageID, L_TCHAR *pszClass); 
      L_VOID OnReceiveReleaseRequest(); 
   }; 
 
   #define SIZEINWORD(p) sizeof(p)/sizeof(L_TCHAR) 
   L_VOID CMyServerConnection::OnReceiveAssociateRequest(LDicomAssociate *pPDU) 
   { 
      LogMessage(TEXT("\tCMyServerConnection::OnReceiveAssociateRequest")); 
 
      //check the version, if not 1, reject it 
      if (pPDU->GetVersion() != 1) 
      { 
         LogMessage(TEXT("\tCMyServerConnection::SendAssociateReject")); 
         SendAssociateReject( 
            PDU_REJECT_RESULT_PERMANENT,  
            PDU_REJECT_SOURCE_USER,  
            PDU_REJECT_REASON_UNKNOWN 
            ); 
      } 
      else 
      {         
         LDicomAssociate DicomAssociate(FALSE); 
 
         L_TCHAR clientAE[20] = {0}; 
         pPDU->GetCalling(clientAE, 20); 
 
         if (lstrcmp(clientAE, TEXT("LEAD_CLIENT")) != 0) 
         { 
            LogMessage(TEXT("\tCMyServerConnection::SendAssociateReject")); 
            SendAssociateReject( 
               PDU_REJECT_RESULT_PERMANENT,  
               PDU_REJECT_SOURCE_USER,  
               PDU_REJECT_REASON_UNKNOWN 
               ); 
            return; 
         } 
 
         //Copy presentation objects from received 
         //Reply that we only support the first Transfer Syntax from the received hPDU 
         L_TCHAR szTransfer[PDU_MAX_UID_SIZE+1] = {0}; 
         L_TCHAR szAbstract[PDU_MAX_UID_SIZE+1] = {0}; 
         L_INT iPresentationCount = pPDU->GetPresentationCount(); 
         for (L_UCHAR i = 0; i<iPresentationCount; i++) 
         { 
            L_UCHAR nId = pPDU->GetPresentation(i); 
            pPDU->GetTransfer(nId, 0, szTransfer, PDU_MAX_UID_SIZE+1); 
            L_UCHAR nResult = PDU_ACCEPT_RESULT_SUCCESS; 
            pPDU->GetAbstract(nId, szAbstract, PDU_MAX_UID_SIZE+1); 
            DicomAssociate.AddPresentation( nId, nResult, szAbstract); 
            DicomAssociate.AddTransfer( nId, szTransfer); 
         } 
 
         LogMessage(TEXT("\tCMyServerConnection::SendAssociateAccept")); 
         SendAssociateAccept(&DicomAssociate); 
      } 
   } 
 
   L_VOID CMyServerConnection::OnReceiveAssociateReject(L_UCHAR nResult, L_UCHAR nSource, L_UCHAR nReason) 
   { 
      L_TCHAR szMsg[200] = {0}; 
      wsprintf(szMsg, TEXT("\tOnReceiveAssociateReject\nResult[%d]\nSource[%d]\nReason[%d]"), nResult, nSource, nReason); 
      LogMessage(szMsg); 
   } 
 
   L_VOID CMyServerConnection::OnReceiveCEchoRequest(L_UCHAR nPresentationID, L_UINT16 nMessageID, L_TCHAR *pszClass) 
   { 
      LogMessage(TEXT("\tCMyServerConnection::OnReceiveCEchoRequest")); 
 
      LogMessage(TEXT("\tCMyServerConnection::SendCEchoResponse")); 
      SendCEchoResponse(nPresentationID, nMessageID, pszClass, COMMAND_STATUS_SUCCESS); 
   } 
 
   L_VOID CMyServerConnection::OnReceiveReleaseRequest() 
   { 
      LogMessage(TEXT("\tCMyServerConnection::OnReceiveReleaseRequest")); 
      LogMessage(TEXT("\tCMyServerConnection::SendReleaseResponse")); 
      SendReleaseResponse(); 
   } 
 
   // ******************************************************************************************* 
   // Server Class  
   // 
   // Listens for connections 
   // When a client connects, this class creates a CMyServerConnection and accepts the connection 
   // ******************************************************************************************* 
   class CMyServer : public LDicomNet 
   { 
   public: 
      CMyServer(L_INT32 nMode): LDicomNet(NULL, nMode) 
      { 
         m_pServerConnection = NULL; 
      } 
 
      ~CMyServer(void) 
      { 
         if (m_pServerConnection != NULL) 
         { 
            delete m_pServerConnection; 
         } 
      } 
 
      L_VOID OnAccept       (L_INT nError); 
      L_VOID OnClose        (L_INT nError, LDicomNet *pServerConnection); 
 
      CMyServerConnection *m_pServerConnection; 
   }; 
 
   L_VOID CMyServer::OnAccept(L_INT nError) 
   { 
      LogMessage(TEXT("\tCMyServer::OnAccept")); 
      if (nError != DICOM_SUCCESS) 
      { 
         return; 
      } 
 
      if (m_pServerConnection != NULL) 
      { 
         delete m_pServerConnection; 
         m_pServerConnection = NULL; 
      } 
 
      m_pServerConnection = new CMyServerConnection(DICOM_SECURE_NONE); 
      if (m_pServerConnection == NULL) 
      { 
         return; 
      } 
 
      nError = LDicomNet::Accept(m_pServerConnection); 
      if (nError != DICOM_SUCCESS) 
      { 
         delete m_pServerConnection; 
         return; 
      } 
   } 
 
   L_VOID CMyServer::OnClose(L_INT nError, LDicomNet *pClient) 
   { 
      LogMessage(TEXT("\tCMyServer::OnClose")); 
      pClient->OnClose(nError, pClient); 
      if (m_pServerConnection == pClient) 
      { 
         m_pServerConnection = NULL; 
      } 
      delete (CMyClient *)pClient; 
   } 
 
   // ******************************************************************************************* 
   // Sample starts here  
   // ******************************************************************************************* 
   #define WaitForProcessing() \ 
   { \ 
      if (!client.Wait()) \ 
      { \ 
         LogMessage(TEXT("Timeout: client.Connect")); \ 
         nRet = DICOM_ERROR_NET_TIME_OUT; \ 
         goto Cleanup; \ 
      } \ 
   }  
 
   L_INT LDicomNet_SendCEchoRequestExample() 
   { 
      LogMessage(TEXT("\n\n *** SendCEchoRequestExample ***")); 
 
      L_TCHAR *pszServerAddress = TEXT("127.0.0.1"); 
      L_UINT uServerPort = 105; 
      L_INT nRet = DICOM_SUCCESS; 
 
      LDicomNet::StartUp(); 
 
      CMyClient client(DICOM_SECURE_NONE); 
      CMyServer server(DICOM_SECURE_NONE); 
      
      LogMessage(TEXT("\tCMyServer::Listen")); 
      nRet = server.Listen(pszServerAddress, uServerPort, 5); 
 
      LogMessage(TEXT("CMyClient::Connect")); 
      client.Connect(NULL, 0, pszServerAddress, uServerPort); 
      if (!client.Wait(2000)) 
      { 
         if (!client.IsConnected()) 
         { 
            LogMessage(TEXT("Timeout: client.Connect"));  
            nRet = DICOM_ERROR_NET_TIME_OUT; 
            goto Cleanup; 
         } 
      } 
 
      if (nRet == DICOM_SUCCESS) 
      { 
         //create the Associate Class as Request 
         LDicomAssociate dicomAssociateRequest(TRUE); 
         dicomAssociateRequest.Default(); 
 
         // Send A-Associate-RQ message 
         dicomAssociateRequest.SetCalled(TEXT("LEAD_SERVER")); 
         dicomAssociateRequest.SetCalling(TEXT("LEAD_CLIENT")); 
 
         LogMessage(TEXT("CMyClient::SendAssociateRequest")); 
         nRet = client.SendAssociateRequest(&dicomAssociateRequest); 
         if (!client.Wait(5000)) 
         { 
            LogMessage(TEXT("Timeout: client.Connect"));  
            nRet = DICOM_ERROR_NET_TIME_OUT; 
            goto Cleanup; 
         } 
      } 
 
      L_UCHAR nPresentationID = client.GetAssociate()->FindAbstract(UID_VERIFICATION_CLASS); 
      L_UINT16 uUniqueID = 99; 
 
      LogMessage(TEXT("CMyClient::SendCEchoRequest")); 
      client.SendCEchoRequest( nPresentationID, uUniqueID, UID_VERIFICATION_CLASS); 
      WaitForProcessing(); 
 
 
      LogMessage(TEXT("CMyClient::SendReleaseRequest")); 
      client.SendReleaseRequest(); 
      WaitForProcessing(); 
 
Cleanup: 
      LogMessage(TEXT("CMyClient::Close")); 
      client.Close(); 
      client.Wait(); 
 
      LogMessage(TEXT("\tCMyServer::Close")); 
      server.Close(); 
 
      LDicomNet::ShutDown(); 
 
      return nRet; 
   } 
 
} 

Help Version 22.0.2022.12.7
Products | Support | Contact Us | Intellectual Property Notices
© 1991-2023 LEAD Technologies, Inc. All Rights Reserved.

LEADTOOLS DICOM C++ Class Library Help
Products | Support | Contact Us | Intellectual Property Notices
© 1991-2023 LEAD Technologies, Inc. All Rights Reserved.