我想使用Kestrel和System.IO.Pipelines包创建一个TCP侦听器。我收到的消息将永远是HL7消息。一个示例消息可以是
MSH|^~&|MegaReg|XYZHospC|SuperOE|XYZImgCtr|20060529090131-0500||ADT^A01^ADT_A01|01052901|P|2.5 EVN\x{e76f}\x{e76f}{##**$$}\x{e76f}{##**$$}\x{e76f}\x{e76f}{##**$}{##**$}##**}\x{e76f}\x{e76f}{##**$}#.{e76f}{##**$}#.{e76f}{##**$$}
唯一需要注意的是,每个传入的HL7消息都以一个垂直制表符开始,这样您就知道消息从哪里开始了。每个HL7消息包含多个段,所以我想我必须遍历每个段。在处理请求之后,我想作为响应发送回一条HL7消息。首先我想出了这个
internal class HL7Listener : ConnectionHandler
{
public override async Task OnConnectedAsync(ConnectionContext connection)
{
IDuplexPipe pipe = connection.Transport;
await FillPipe(pipe.Output);
await ReadPipe(pipe.Input);
}
private async Task FillPipe(PipeWriter pipeWriter)
{
const int minimumBufferSize = 512;
while (true)
{
Memory<byte> memory = pipeWriter.GetMemory(minimumBufferSize);
try
{
int bytesRead = 32; // not sure what to do here
if (bytesRead == 0)
{
break;
}
pipeWriter.Advance(bytesRead);
}
catch (Exception ex)
{
// ... something failed ...
break;
}
FlushResult result = await pipeWriter.FlushAsync();
if (result.IsCompleted)
{
break;
}
}
pipeWriter.Complete();
}
private async Task ReadPipe(PipeReader pipeReader)
{
while (true)
{
ReadResult result = await pipeReader.ReadAsync();
ReadOnlySequence<byte> buffer = result.Buffer;
SequencePosition? position;
do
{
position = buffer.PositionOf((byte)'\v');
if (position != null)
{
ReadOnlySequence<byte> line = buffer.Slice(0, position.Value);
// ... Process the line ...
buffer = buffer.Slice(buffer.GetPosition(1, position.Value));
}
}
while (position != null);
pipeReader.AdvanceTo(buffer.Start, buffer.End);
if (result.IsCompleted)
{
break;
}
}
pipeReader.Complete();
}
}不幸的是,我正在为一些事情而挣扎:
int bytesRead = 32;部分,我如何知道已经读取了多少字节?或者如何使用作者实例进行阅读?// ... Process the line ...的代码。基本上,我必须提取整个HL7消息,这样我就可以使用HL7解析器来转换消息字符串。await ReadPipe(pipe.Input);之后?通过使用await connection.Transport.Output.WriteAsync(/* the HL7 message to send back */);发布于 2020-09-22 14:47:05
你见过大卫·福勒( David )的TcpEcho例子吗?我想说这是相当典型的,因为他是那个发布了devblog System.IO.Pipelines公告的人。
他的例子涉及原始套接字。我已经将其改编为ConnectionHandler API和HL7消息(但是,我对HL7知之甚少):
internal class HL7Listener : ConnectionHandler
{
public override async Task OnConnectedAsync(ConnectionContext connection)
{
while (true)
{
var result = await connection.Transport.Input.ReadAsync();
var buffer = result.Buffer;
while (TryReadMessage(ref buffer, out ReadOnlySequence<byte> hl7Message))
{
// Process the line.
var response = ProcessMessage(hl7Message);
await connection.Transport.Output.WriteAsync(response);
}
if (result.IsCompleted)
{
break;
}
connection.Transport.Input.AdvanceTo(buffer.Start, buffer.End);
}
}
public static bool TryReadMessage(ref ReadOnlySequence<byte> buffer, out ReadOnlySequence<byte> hl7Message)
{
var endOfMessage = buffer.PositionOf((byte)0x1C);
if (endOfMessage == null || !TryMatchNextByte(ref buffer, endOfMessage.Value, 0x0D, out var lastBytePosition))
{
hl7Message = default;
return false;
}
var messageBounds = buffer.GetPosition(1, lastBytePosition.Value); // Slice() is exclusive on the upper bound
hl7Message = buffer.Slice(0, messageBounds);
buffer = buffer.Slice(messageBounds); // remove message from buffer
return true;
}
/// <summary>
/// Does the next byte after currentPosition match the provided value?
/// </summary>
private static bool TryMatchNextByte(ref ReadOnlySequence<byte> buffer, SequencePosition currentPosition, byte value, out SequencePosition? nextPosition)
{
nextPosition = buffer.Slice(currentPosition).PositionOf(value);
if(nextPosition == null || !nextPosition.Value.Equals(buffer.GetPosition(1, currentPosition)))
{
nextPosition = null;
return false;
}
return true;
}
private ReadOnlyMemory<byte> ProcessMessage(ReadOnlySequence<byte> hl7Message)
{
var incomingMessage = Encoding.UTF8.GetString(hl7Message.ToArray());
// do something with the message and generate your response. I'm using UTF8 here
// but not sure if that's valid for HL7.
return Encoding.UTF8.GetBytes("Response message: OK!");
}
}更新:添加了关于HL7消息结构的最新信息。
https://stackoverflow.com/questions/63951596
复制相似问题