Dreamine.Communication.Core
1.0.2
Dreamine.Communication.Core 통신 기능과 관련 API를 제공합니다.
Toggle main menu visibility
로딩중...
검색중...
일치하는것 없음
DelimiterMessageFrameCodec.cs
이 파일의 문서화 페이지로 가기
1
using
System.Runtime.CompilerServices;
2
using
System.Text;
3
4
namespace
Dreamine.Communication.Core.Framing
;
5
14
public
sealed
class
DelimiterMessageFrameCodec
:
IMessageFrameCodec
15
{
24
private
readonly
byte
[]
_delimiter
;
33
private
readonly
int
_maxFrameLength
;
42
private
readonly ConditionalWeakTable<Stream, FrameReadBuffer>
_readBuffers
=
new
();
43
52
public
DelimiterMessageFrameCodec
()
53
: this(
"\r\n"
, Encoding.UTF8, 1024 * 1024)
54
{
55
}
56
113
public
DelimiterMessageFrameCodec
(
114
string
delimiter,
115
Encoding encoding,
116
int
maxFrameLength)
117
{
118
ArgumentException.ThrowIfNullOrEmpty(delimiter);
119
ArgumentNullException.ThrowIfNull(encoding);
120
121
if
(maxFrameLength <= 0)
122
{
123
throw
new
ArgumentOutOfRangeException(nameof(maxFrameLength));
124
}
125
126
_delimiter
= encoding.GetBytes(delimiter);
127
_maxFrameLength
= maxFrameLength;
128
}
129
186
public
async Task
WriteFrameAsync
(
187
Stream stream,
188
byte
[] payload,
189
CancellationToken cancellationToken =
default
)
190
{
191
ArgumentNullException.ThrowIfNull(stream);
192
ArgumentNullException.ThrowIfNull(payload);
193
194
await stream.WriteAsync(payload, cancellationToken).ConfigureAwait(
false
);
195
await stream.WriteAsync(
_delimiter
, cancellationToken).ConfigureAwait(
false
);
196
await stream.FlushAsync(cancellationToken).ConfigureAwait(
false
);
197
}
198
255
public
async Task<byte[]?>
ReadFrameAsync
(
256
Stream stream,
257
CancellationToken cancellationToken =
default
)
258
{
259
ArgumentNullException.ThrowIfNull(stream);
260
261
var frame =
new
List<byte>(Math.Min(
_maxFrameLength
, 4096));
262
var temp =
new
byte
[Math.Min(
_maxFrameLength
, 4096)];
263
var readBuffer =
_readBuffers
.GetValue(stream, _ =>
new
FrameReadBuffer
());
264
265
while
(
true
)
266
{
267
if
(
TryConsumeBufferedBytes
(readBuffer, frame, out var frameBytes))
268
{
269
return
frameBytes;
270
}
271
272
var read = await stream.ReadAsync(
273
temp.AsMemory(0, temp.Length),
274
cancellationToken)
275
.ConfigureAwait(
false
);
276
277
if
(read == 0)
278
{
279
return
frame.Count == 0
280
? null
281
: frame.ToArray();
282
}
283
284
lock (readBuffer.SyncRoot)
285
{
286
for
(var index = 0; index < read; index++)
287
{
288
readBuffer.Pending.Enqueue(temp[index]);
289
}
290
}
291
}
292
}
293
342
private
bool
TryConsumeBufferedBytes
(
343
FrameReadBuffer
readBuffer,
344
List<byte> frame,
345
out
byte
[]? result)
346
{
347
result =
null
;
348
349
lock (readBuffer.
SyncRoot
)
350
{
351
while
(readBuffer.
Pending
.Count > 0)
352
{
353
frame.Add(readBuffer.
Pending
.Dequeue());
354
355
if
(frame.Count >
_maxFrameLength
)
356
{
357
throw
new
InvalidDataException(
358
$
"Frame length exceeded. MaxFrameLength={_maxFrameLength}"
);
359
}
360
361
if
(!
EndsWithDelimiter
(frame))
362
{
363
continue
;
364
}
365
366
frame.RemoveRange(
367
frame.Count -
_delimiter
.Length,
368
_delimiter
.Length);
369
370
result = frame.ToArray();
371
return
true
;
372
}
373
}
374
375
return
false
;
376
}
377
402
private
bool
EndsWithDelimiter
(List<byte> frame)
403
{
404
if
(frame.Count <
_delimiter
.Length)
405
{
406
return
false
;
407
}
408
409
var start = frame.Count -
_delimiter
.Length;
410
411
for
(var index = 0; index <
_delimiter
.Length; index++)
412
{
413
if
(frame[start + index] !=
_delimiter
[index])
414
{
415
return
false
;
416
}
417
}
418
419
return
true
;
420
}
421
430
private
sealed
class
FrameReadBuffer
431
{
440
public
object
SyncRoot
{
get
; } =
new
();
441
450
public
Queue<byte>
Pending
{
get
; } = [];
451
}
452
}
Dreamine.Communication.Core.Framing
Definition
DelimiterMessageFrameCodec.cs:4
Dreamine.Communication.Core.Framing.DelimiterMessageFrameCodec.WriteFrameAsync
async Task WriteFrameAsync(Stream stream, byte[] payload, CancellationToken cancellationToken=default)
Definition
DelimiterMessageFrameCodec.cs:186
Dreamine.Communication.Core.Framing.DelimiterMessageFrameCodec._maxFrameLength
readonly int _maxFrameLength
Definition
DelimiterMessageFrameCodec.cs:33
Dreamine.Communication.Core.Framing.DelimiterMessageFrameCodec.ReadFrameAsync
async Task< byte[]?> ReadFrameAsync(Stream stream, CancellationToken cancellationToken=default)
Definition
DelimiterMessageFrameCodec.cs:255
Dreamine.Communication.Core.Framing.DelimiterMessageFrameCodec._delimiter
readonly byte[] _delimiter
Definition
DelimiterMessageFrameCodec.cs:24
Dreamine.Communication.Core.Framing.DelimiterMessageFrameCodec.EndsWithDelimiter
bool EndsWithDelimiter(List< byte > frame)
Definition
DelimiterMessageFrameCodec.cs:402
Dreamine.Communication.Core.Framing.DelimiterMessageFrameCodec.DelimiterMessageFrameCodec
DelimiterMessageFrameCodec(string delimiter, Encoding encoding, int maxFrameLength)
Definition
DelimiterMessageFrameCodec.cs:113
Dreamine.Communication.Core.Framing.DelimiterMessageFrameCodec.TryConsumeBufferedBytes
bool TryConsumeBufferedBytes(FrameReadBuffer readBuffer, List< byte > frame, out byte[]? result)
Definition
DelimiterMessageFrameCodec.cs:342
Dreamine.Communication.Core.Framing.DelimiterMessageFrameCodec.DelimiterMessageFrameCodec
DelimiterMessageFrameCodec()
Definition
DelimiterMessageFrameCodec.cs:52
Dreamine.Communication.Core.Framing.DelimiterMessageFrameCodec._readBuffers
readonly ConditionalWeakTable< Stream, FrameReadBuffer > _readBuffers
Definition
DelimiterMessageFrameCodec.cs:42
Dreamine.Communication.Core.Framing.DelimiterMessageFrameCodec.FrameReadBuffer
Definition
DelimiterMessageFrameCodec.cs:431
Dreamine.Communication.Core.Framing.DelimiterMessageFrameCodec.FrameReadBuffer.Pending
Queue< byte > Pending
Definition
DelimiterMessageFrameCodec.cs:450
Dreamine.Communication.Core.Framing.DelimiterMessageFrameCodec.FrameReadBuffer.SyncRoot
object SyncRoot
Definition
DelimiterMessageFrameCodec.cs:440
Dreamine.Communication.Core.Framing.IMessageFrameCodec
Definition
IMessageFrameCodec.cs:16
Framing
DelimiterMessageFrameCodec.cs
다음에 의해 생성됨 :
1.17.0