【问题标题】:How to implement send and receive hl7 data in .NET in ssh connection如何在 .NET 中通过 ssh 连接实现发送和接收 hl7 数据
【发布时间】:2019-10-08 00:44:31
【问题描述】:

我正在.Net 中实现一个应用程序。我必须通过 SSH 创建一个有效的连接,但是 HL7 数据接收失败。目的地是树莓派。因此,当我调试 ssh 客户端已连接时,端口已转发,tcp 客户端也已连接,但我的查询没有答案。请给我一些例子!

在这个项目中,我已经在 Android 上实现了它——它运行良好。 所以在 .Net 中我尝试了 NHapiTools 库,我也尝试了直接的 TcpClient 方式。本地端口 = 远程端口。我用 localIP = "localhost"

static void Main(string[] args)
    {
        try
        {
            PrivateKeyFile file = new PrivateKeyFile(@"./key/private.key");
        using (var client = new SshClient(remoteIP, sshPort, username, file))
            {
                client.Connect();
                var ci = client.ConnectionInfo;
                var port = new ForwardedPortLocal(localIP, localPort, client.ConnectionInfo.Host, remotePort);
                client.AddForwardedPort(port);
                port.Start();
                var req = "MSH|^~\\&|TestAppName||AVR||20181107201939.357+0000||QRY^R02^QRY_R02|923456|P|2.5";

                ////TCP
                var tcpClient = new TcpClient();
                tcpClient.Connect(localIP, (int)localPort);
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(req);

                using (var stream = tcpClient.GetStream())
                {
                    stream.Write(data, 0, data.Length);

                    using (var buffer = new MemoryStream())
                    {
                        byte[] chunk = new byte[4096];
                        int bytesRead;

                        while ((bytesRead = stream.Read(chunk, 0, chunk.Length)) > 0)
                        {
                            buffer.Write(chunk, 0, bytesRead);
                        }

                        data = buffer.ToArray();
                    }
                }
   //I used this also with same result -> no respond
   //SimpleMLLP
   /*
   var connection = new SimpleMLLPClient(localIP, localPort, 
   Encoding.UTF8);
   var response = connection.SendHL7Message(req);
   */
            }
        }

        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
        Console.ReadLine();
    }

}

所以我发现 TCP 中的缓冲区大小为 0(由于超时)。在 SimpleMLLP 测试中,SendHK7Message 方法永远不会返回

【问题讨论】:

    标签: c# .net ssh hl7 mllp


    【解决方案1】:

    您在发送消息时没有实现MLLP(也称为 LLP)协议。

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

    这样,当您向侦听器(TCP/MLLP 服务器)发送消息时,它会在您的传入数据中查找 Start Block。它永远找不到它。考虑到垃圾,它只会丢弃您的整个消息。因此,您不会从 Listener 那里得到任何回报。

    实施 MLLP 后,您的消息(您在套接字上写入的内容)应该如下所示某事

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

    请注意,&lt;VT&gt;&lt;CR&gt;&lt;FS&gt; 是上述消息中的占位符。

    您可以参考this 文章了解详细信息(阅读第 4 步及以后):

    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();
                }
            }
        }
    }
    

    您应该修改以下代码行:

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

    更多开源代码可以参考thisgithub项目。

    【讨论】:

      【解决方案2】:

      经过几天的努力,我已经解决了这个问题。主要错误在于端口转发。 我建议使用 Renci 的 SSH.Net(Tamir ssh 存在算法错误)。 创建 ssh 连接后,我使用它进行端口转发:

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

      在 cmd 中使用 ipconfig /all 检查您的本地 IP。或者使用 127.0.0.1 作为回环 IP。 SimpleMLLPClient 对我不起作用,所以我使用了直接 tcp 客户端查询方式。像这样:

                  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);
                  }
      

      所以它给了我 0 字节的即时答案(不是由于超时)。 Amit Joshi 的帮助来了。我用 START_OF_BLOCK、CARRIAGE_RETURN 和 END_OF_BLOCK 查询了他的建议,终于开始工作了。谢谢阿米特·乔希!

      附加信息: 在 Android (java/Kotlin) 中,jsch 会话 setPortForwardingL 可以使用三个参数正常工作:

              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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-12
        • 1970-01-01
        • 2015-07-07
        • 1970-01-01
        • 2012-08-22
        相关资源
        最近更新 更多