Dreamine.Communication.Core 1.0.2
Dreamine.Communication.Core 통신 기능과 관련 API를 제공합니다.
로딩중...
검색중...
일치하는것 없음
LengthPrefixedMessageFrameCodec.cs
이 파일의 문서화 페이지로 가기
1using System.Buffers.Binary;
2
4
14{
23 private const int HeaderSize = 4;
24
33 private readonly int _maxFrameLength;
34
44 : this(1024 * 1024)
45 {
46 }
47
72 public LengthPrefixedMessageFrameCodec(int maxFrameLength)
73 {
74 if (maxFrameLength <= 0)
75 {
76 throw new ArgumentOutOfRangeException(nameof(maxFrameLength));
77 }
78
79 _maxFrameLength = maxFrameLength;
80 }
81
154 public async Task WriteFrameAsync(
155 Stream stream,
156 byte[] payload,
157 CancellationToken cancellationToken = default)
158 {
159 ArgumentNullException.ThrowIfNull(stream);
160 ArgumentNullException.ThrowIfNull(payload);
161
162 if (payload.Length > _maxFrameLength)
163 {
164 throw new InvalidDataException(
165 $"Frame length exceeded. Length={payload.Length}, MaxFrameLength={_maxFrameLength}");
166 }
167
168 var header = new byte[HeaderSize];
169 BinaryPrimitives.WriteInt32BigEndian(header, payload.Length);
170
171 await stream.WriteAsync(header, cancellationToken).ConfigureAwait(false);
172 await stream.WriteAsync(payload, cancellationToken).ConfigureAwait(false);
173 await stream.FlushAsync(cancellationToken).ConfigureAwait(false);
174 }
175
232 public async Task<byte[]?> ReadFrameAsync(
233 Stream stream,
234 CancellationToken cancellationToken = default)
235 {
236 ArgumentNullException.ThrowIfNull(stream);
237
238 var header = await ReadExactAsync(stream, HeaderSize, cancellationToken)
239 .ConfigureAwait(false);
240
241 if (header is null)
242 {
243 return null;
244 }
245
246 var length = BinaryPrimitives.ReadInt32BigEndian(header);
247
248 if (length < 0 || length > _maxFrameLength)
249 {
250 throw new InvalidDataException(
251 $"Invalid frame length. Length={length}, MaxFrameLength={_maxFrameLength}");
252 }
253
254 if (length == 0)
255 {
256 return Array.Empty<byte>();
257 }
258
259 return await ReadExactAsync(stream, length, cancellationToken)
260 .ConfigureAwait(false);
261 }
262
319 private static async Task<byte[]?> ReadExactAsync(
320 Stream stream,
321 int length,
322 CancellationToken cancellationToken)
323 {
324 var buffer = new byte[length];
325 var offset = 0;
326
327 while (offset < length)
328 {
329 var read = await stream.ReadAsync(
330 buffer.AsMemory(offset, length - offset),
331 cancellationToken)
332 .ConfigureAwait(false);
333
334 if (read == 0)
335 {
336 return null;
337 }
338
339 offset += read;
340 }
341
342 return buffer;
343 }
344}
async Task WriteFrameAsync(Stream stream, byte[] payload, CancellationToken cancellationToken=default)
async Task< byte[]?> ReadFrameAsync(Stream stream, CancellationToken cancellationToken=default)
static async Task< byte[]?> ReadExactAsync(Stream stream, int length, CancellationToken cancellationToken)