How to implement send and receive hl7 data in .NET in ssh connection

前端 未结 2 381
粉色の甜心
粉色の甜心 2021-01-16 09:52

I\'m implementing an application in .Net. I have to create a connection by SSH which is works, but the HL7 data receiving fails. The destination is a raspberry pi. So when I

相关标签:
2条回答
  • 2021-01-16 10:15

    You are not implementing MLLP (also called LLP) protocol while sending message.

    Description                 HEX     ASCII   Symbol
    Message starting character  0B      11      <VT>
    Message ending characters   1C,0D   28,13   <FS>,<CR>
    

    This way, when you send a message to Listener (TCP/MLLP server), it looks for Start Block in your incoming data. It never finds it. It just discards your entire message considering garbage. Hence, you get nothing back from Listener.

    With MLLP implemented, your message (the stuff you are writing on socket) should look something like below:

    <VT>MSH|^~\\&|TestAppName||AVR||20181107201939.357+0000||QRY^R02^QRY_R02|923456|P|2.5<FS><CR>
    

    Note the <VT>, <CR> and <FS> are place holders in above message.

    You may refer to this article for detailed information (Read step 4 and onward):

    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    namespace SimpleMllpHl7ClientAdvanced
    {
        public class Program
        {
            private static char END_OF_BLOCK = '\u001c';
            private static char START_OF_BLOCK = '\u000b';
            private static char CARRIAGE_RETURN = (char)13;
            static void Main(string[] args)
            {
                TcpClient ourTcpClient = null;
                NetworkStream networkStream = null;
                var testHl7MessageToTransmit = new StringBuilder();
                //a HL7 test message that is enveloped with MLLP as described in my article
                testHl7MessageToTransmit.Append(START_OF_BLOCK)
                    .Append("MSH|^~\\&|AcmeHIS|StJohn|CATH|StJohn|20061019172719||ORM^O01|MSGID12349876|P|2.3")
                    .Append(CARRIAGE_RETURN)
                    .Append("PID|||20301||Durden^Tyler^^^Mr.||19700312|M|||88 Punchward Dr.^^Los Angeles^CA^11221^USA|||||||")
                    .Append(CARRIAGE_RETURN)
                    .Append("PV1||O|OP^^||||4652^Paulson^Robert|||OP|||||||||9|||||||||||||||||||||||||20061019172717|20061019172718")
                    .Append(CARRIAGE_RETURN)
                    .Append("ORC|NW|20061019172719")
                    .Append(CARRIAGE_RETURN)
                    .Append("OBR|1|20061019172719||76770^Ultrasound: retroperitoneal^C4|||12349876")
                    .Append(CARRIAGE_RETURN)
                    .Append(END_OF_BLOCK)
                    .Append(CARRIAGE_RETURN);
                try
                {
                    //initiate a TCP client connection to local loopback address at port 1080
                    ourTcpClient = new TcpClient();
                    ourTcpClient.Connect(new IPEndPoint(IPAddress.Loopback, 1080));
                    Console.WriteLine("Connected to server....");
                    //get the IO stream on this connection to write to
                    networkStream = ourTcpClient.GetStream();
                    //use UTF-8 and either 8-bit encoding due to MLLP-related recommendations
                    var sendMessageByteBuffer = Encoding.UTF8.GetBytes(testHl7MessageToTransmit.ToString());
                    if (networkStream.CanWrite)
                    {
                        //send a message through this connection using the IO stream
                        networkStream.Write(sendMessageByteBuffer, 0, sendMessageByteBuffer.Length);
                        Console.WriteLine("Data was sent data to server successfully....");
                        var receiveMessageByteBuffer = Encoding.UTF8.GetBytes(testHl7MessageToTransmit.ToString());
                        var bytesReceivedFromServer = networkStream.Read(receiveMessageByteBuffer, 0, receiveMessageByteBuffer.Length);
                        // Our server for this example has been designed to echo back the message
                        // keep reading from this stream until the message is echoed back
                        while (bytesReceivedFromServer > 0)
                        {
                            if (networkStream.CanRead)
                            {
                                bytesReceivedFromServer = networkStream.Read(receiveMessageByteBuffer, 0, receiveMessageByteBuffer.Length);
                                if (bytesReceivedFromServer == 0)
                                {
                                    break;
                                }
                            }                            
                        }
                        var receivedMessage = Encoding.UTF8.GetString(receiveMessageByteBuffer);
                        Console.WriteLine("Received message from server: {0}", receivedMessage);
                    }
                    Console.WriteLine("Press any key to exit...");
                    Console.ReadLine();
                }
                catch (Exception ex)
                {
                    //display any exceptions that occur to console
                    Console.WriteLine(ex.Message);
                }
                finally
                {
                    //close the IO strem and the TCP connection
                    networkStream?.Close();
                    ourTcpClient?.Close();
                }
            }
        }
    }
    

    You should modify your following line of code as below:

    var req = START_OF_BLOCK + "MSH|^~\\&|TestAppName||AVR||20181107201939.357+0000||QRY^R02^QRY_R02|923456|P|2.5" + END_OF_BLOCK + CARRIAGE_RETURN;
    

    For more open source code, you may refer to this github project.

    0 讨论(0)
  • 2021-01-16 10:35

    After days of struggling I have solved the problem. The main error was with the port forwarding. I would reccomend to use SSH.Net by Renci (There was algorithm error with Tamir ssh). After ssh connection created I used this to port forward:

               var port = new ForwardedPortLocal(localIP, localPort, "localhost", remotePort);
    

    Check your localIP with ipconfig /all in cmd. Or use 127.0.0.1 as a loopback IP. SimpleMLLPClient did not worked for me so I used the direct tcp client query way. Like this:

                TcpClient ourTcpClient = new TcpClient();
                ourTcpClient.Connect(localIP, (int)localPort); 
                NetworkStream networkStream = ourTcpClient.GetStream();
    
                var sendMessageByteBuffer = Encoding.UTF8.GetBytes(testHl7MessageToTransmit.ToString());
    
                if (networkStream.CanWrite)
                {
                    networkStream.Write(sendMessageByteBuffer, 0, sendMessageByteBuffer.Length);
    
                    Console.WriteLine("Data was sent to server successfully....");
                    byte[] receiveMessageByteBuffer = new byte[ourTcpClient.ReceiveBufferSize];
                    var bytesReceivedFromServer = networkStream.Read(receiveMessageByteBuffer, 0, receiveMessageByteBuffer.Length);
    
                    if (bytesReceivedFromServer > 0 && networkStream.CanRead)
                    {
                        receivedMessage.Append(Encoding.UTF8.GetString(receiveMessageByteBuffer));
                    }
    
                    var message = receivedMessage.Replace("\0", string.Empty);
                    Console.WriteLine("Received message from server: {0}", message);
                }
    

    So it gave me instant answer with 0 bytes (not due timeout). And here comes Amit Joshi help. I used a query what he suggested with START_OF_BLOCK, CARRIAGE_RETURN and END_OF_BLOCK and finally started to work. Thank you Amit Joshi!

    Additional info: In Android (java/Kotlin) jsch session setPortForwardingL works fine with three params:

            val session = jsch.getSession("user", sshIP, sshPort)
            session.setPassword("")
            jsch.addIdentity(privatekey.getAbsolutePath())
            // Avoid asking for key confirmation
            val prop = Properties()
            prop.setProperty("StrictHostKeyChecking", "no")
            session.setConfig(prop)
            session.connect(5000)
            session.setPortForwardingL(localForwardPort, "localhost", remotePort)
    
            val useTls = false
            val context = DefaultHapiContext()
            connection = context.newClient("localhost", localForwardPort, useTls)
    
    0 讨论(0)
提交回复
热议问题