C-STORE over slow connection

345 views
Skip to first unread message

Hesham Desouky

unread,
Feb 18, 2015, 8:55:03 AM2/18/15
to fo-d...@googlegroups.com
Hello all,

Currently I am developing a solution where our PACS system forward studies from branch to central hub through C-STORE.

The connection between the branch and C-STORE is an ordinary internet line with 4Mbps download and 1Mbps upload.

There is a weird issue occurs, sometimes the C-STORE operation freezes and no exception thrown.

I investigated the opened ports between the client and the server and both have the connection established with no activities.

Restarting the branch application and the C-STORE operation continues normally.

Am I missing something?

Below is a code describes my operation

void Send(ip,port,callingAet,calledAet)
{
                var client = new DicomClient();
                foreach (var sop in _sopList)
                {
                    var request = new DicomCStoreRequest(sop);
                    request.UserState = sop;
                    
                    request.OnResponseReceived = OnResponseReceived;
                    client.AddRequest(request);
                }

                client.Send(ip,port, false, callingAet,calledAet);
}

void OnResponseReceived(DicomCStoreRequest request, DicomCStoreResponse response)
{
            var sop = request.UserState as Entities.WorkQueueSop;
            if (sop != null)
            {
                if (response.Status.State == DicomState.Success)
                { 
                       //log success

                }
                else
                {
                     //log failure
                }
            }
}

Hesham Desouky

unread,
Feb 22, 2015, 3:11:43 AM2/22/15
to fo-d...@googlegroups.com
Any thoughts guys?

Chris Horn

unread,
Feb 23, 2015, 3:15:32 AM2/23/15
to fo-d...@googlegroups.com
Hesham,

sounds like a timing issue, have you tried separating the foreach into a seperate function?
from memory we had a similar issue with our Dicom send so we separated out the the request generation to a separate function so when we call send it thats all we were calling.
Haven't seen an issue since we use this process to send 5 TB of images each day to an Archive.
 

Chris Horn

unread,
Feb 23, 2015, 5:16:45 AM2/23/15
to fo-d...@googlegroups.com
Hesham,
I've been giving this one some thought, our C-Store SCP is based on the SCP supplied in fo-Dicom samples folder.
Our DICOM Client runs as a windows Service. It gathers images based on an "Requests" being put on a Queue.
The process of gathering Images may in involve Coercing Dicom Tags before sending, and may also Transfer syntax changing although this is not standard...
normally its negotiated as part of the accociation.

then we send the files using the following code, we use a Queue so the DICOM files sty on the queue until a successful C-Store responce is recived
    private void CStoreFiles(IList<string> files, string remoteAETitle, string remoteHostName, int dicomPort, DicomTransferSyntax preferredTransferSyntax)
    {
        try
        {
            var cStoreClient = new Dicom.Network.DicomClient
                {
                    Options = new DicomServiceOptions { TcpNoDelay = !_useNagle },
                    Linger = 200,
                };

            // enqueue files for sending
            var filesToSend = 0;
            foreach (var file in files)
            {
                try
                {
                    var dicomFile = DicomFile.Open(file);
                    var currentTransferSyntax = dicomFile.Dataset.Get<DicomTransferSyntax>(DicomTag.TransferSyntaxUID);
                    _logger.Debug("Adding request for " + file);

                    var f = file;
                    var req = new DicomCStoreRequest(dicomFile)
                        {
                            OnResponseReceived = (request, response) => OnResponseReceived(request, response, auditManager, f),
                            AdditionalTransferSyntaxes = preferredTransferSyntax != null ? new[] { preferredTransferSyntax } : new[] { currentTransferSyntax }
                        };

                    cStoreClient.AddRequest(req);
                    filesToSend++;
                }
                catch (Exception ex)
                {
                    _logger.Debug("Error Opening " + file + " " + Environment.NewLine + FlattenException(ex));
                }
            }

            // ensure all files were enqueued properly
            if (filesToSend != files.Count())
                throw new Exception("Aborting request because some files could not be enqueued.");

            // calculate total file size, start a send timer and send files
            _logger.Info("Sending files to " + remoteHostName + " : " + remoteAETitle + "...");
            var totalFileSize = files.Sum(file => new FileInfo(file).Length);
            var s = new Stopwatch();
            s.Start();
            cStoreClient.Send(remoteHostName, dicomPort, false, _localAETitle, remoteAETitle);
            _logger.Info("Sent " + files.Count() + " files of " + totalFileSize + " Bytes, in " + (double)s.ElapsedMilliseconds + " ms at " + (totalFileSize * 1000 / (double)s.ElapsedMilliseconds / 1024 / 1024).ToString("F2") + "MB/Sec.");
        }
        catch (Exception ex)
        {
            // quarantine remaining files
            foreach (var file in files)
                QuarantineFile(file);
            throw new Exception("Error performing dicom C-Store request.", ex);
        }
    }

Hesham Desouky

unread,
Feb 24, 2015, 1:02:16 PM2/24/15
to fo-d...@googlegroups.com
Hello Chriss,

Thanks for the example. This is pretty similar to what I do. I have a work queue that process an auto routing/forwarding request to send study sop files to remove server.

But I don't manipulate DICOM files before sending it and I didn't set the Linger to 200 or turned off TcpNoDelay. Should I do this? Why?

One more thing, my remote server is not in the local network, it is a virtual machine hosted in Amazon EC2 services with limited upload speed (512 kbps) from the client side (the sender).

Thanks

Hesham
Reply all
Reply to author
Forward
0 new messages