Files
lserp_cs_6.0/插件库/Lskj.AgentPet.Host.Core/ErpBridge/BridgeFrameCodec.cs
T
2026-08-14 14:28:28 +08:00

54 lines
2.0 KiB
C#

using System.Buffers.Binary;
namespace Lskj.AgentPet.Host.Core.ErpBridge;
public static class BridgeFrameCodec
{
public const int MaxMessageBytes = 1024 * 1024;
public static async Task WriteAsync(
Stream stream,
ReadOnlyMemory<byte> body,
CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(stream);
if (body.Length is <= 0 or > MaxMessageBytes)
throw new HostError("bridge_protocol_error", "ERP 桥请求长度无效或超过 1 MB。");
byte[] header = new byte[4];
BinaryPrimitives.WriteInt32LittleEndian(header, body.Length);
await stream.WriteAsync(header, cancellationToken).ConfigureAwait(false);
await stream.WriteAsync(body, cancellationToken).ConfigureAwait(false);
await stream.FlushAsync(cancellationToken).ConfigureAwait(false);
}
public static async Task<byte[]> ReadAsync(
Stream stream,
CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(stream);
byte[] header = new byte[4];
await ReadExactlyAsync(stream, header, cancellationToken).ConfigureAwait(false);
int length = BinaryPrimitives.ReadInt32LittleEndian(header);
if (length is <= 0 or > MaxMessageBytes)
throw new HostError("bridge_protocol_error", "ERP 桥响应长度无效或超过 1 MB。");
byte[] body = new byte[length];
await ReadExactlyAsync(stream, body, cancellationToken).ConfigureAwait(false);
return body;
}
private static async Task ReadExactlyAsync(
Stream stream,
Memory<byte> target,
CancellationToken cancellationToken)
{
int offset = 0;
while (offset < target.Length)
{
int count = await stream.ReadAsync(target[offset..], cancellationToken).ConfigureAwait(false);
if (count == 0)
throw new HostError("bridge_disconnected", "ERP 桥在完整消息到达前关闭。");
offset += count;
}
}
}