.NET中ssh连接如何实现发送和接收hl7数据
How to implement send and receive hl7 data in .NET in ssh connection
我正在 .Net 中实现一个应用程序。我必须通过可用的 SSH 创建连接,但 HL7 数据接收失败。目的地是 raspberry pi。因此,当我调试时,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 方法中从不 returns
您在发送消息时没有实施 MLLP(也称为 LLP)协议。
Description HEX ASCII Symbol
Message starting character 0B 11 <VT>
Message ending characters 1C,0D 28,13 <FS>,<CR>
这样,当您向 Listener(TCP/MLLP 服务器)发送消息时,它会在您的传入数据中查找起始块。它永远找不到它。考虑到垃圾,它只是丢弃您的整个消息。因此,您从 Listener 得不到任何回报。
实施 MLLP 后,您的消息(您在套接字上写入的内容)应该看起来类似,如下所示:
<VT>MSH|^~\&|TestAppName||AVR||20181107201939.357+0000||QRY^R02^QRY_R02|923456|P|2.5<FS><CR>
请注意,<VT>
、<CR>
和 <FS>
是上述消息中的占位符。
您可以参考 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项目
经过几天的努力,我已经解决了这个问题。主要错误是端口转发。
我建议使用 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("[=11=]", 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)
我正在 .Net 中实现一个应用程序。我必须通过可用的 SSH 创建连接,但 HL7 数据接收失败。目的地是 raspberry pi。因此,当我调试时,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 方法中从不 returns
您在发送消息时没有实施 MLLP(也称为 LLP)协议。
Description HEX ASCII Symbol
Message starting character 0B 11 <VT>
Message ending characters 1C,0D 28,13 <FS>,<CR>
这样,当您向 Listener(TCP/MLLP 服务器)发送消息时,它会在您的传入数据中查找起始块。它永远找不到它。考虑到垃圾,它只是丢弃您的整个消息。因此,您从 Listener 得不到任何回报。
实施 MLLP 后,您的消息(您在套接字上写入的内容)应该看起来类似,如下所示:
<VT>MSH|^~\&|TestAppName||AVR||20181107201939.357+0000||QRY^R02^QRY_R02|923456|P|2.5<FS><CR>
请注意,<VT>
、<CR>
和 <FS>
是上述消息中的占位符。
您可以参考 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项目
经过几天的努力,我已经解决了这个问题。主要错误是端口转发。 我建议使用 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("[=11=]", 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)