Files
jeon 096111e983 feat: 06-17 신규 작업본 반영 (개발사양서/기능검토/승인원/Source 등 추가)
.claude/ 제외(.gitignore 추가). 기존 초기커밋(5a96a69) 위에 신규·수정·이동분 커밋.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 07:54:58 +09:00

57 lines
1.8 KiB
C#

namespace CvnetPacketProgram;
/// <summary>
/// 수신 바이트 스트림에서 0xF7 0x32 로 시작하는 완전한 프레임을 추출한다.
/// 프레임 길이 = 5(Header~Len) + Len + 2(XOR,ADD).
/// </summary>
public sealed class FrameParser
{
private readonly List<byte> _buf = new();
public void Append(byte[] data, int len)
{
for (int i = 0; i < len; i++) _buf.Add(data[i]);
}
/// <summary>버퍼에서 추출 가능한 모든 완전 프레임을 반환한다.</summary>
public List<byte[]> Extract()
{
var result = new List<byte[]>();
while (true)
{
// Header(0xF7) + Device(0x32) 동기화
int sync = FindSync();
if (sync < 0)
{
// 동기 패턴 없음 — 마지막 1바이트(0xF7 가능성)만 남기고 버림
if (_buf.Count > 1) _buf.RemoveRange(0, _buf.Count - 1);
break;
}
if (sync > 0) _buf.RemoveRange(0, sync); // 앞쪽 쓰레기 제거
if (_buf.Count < 5) break; // Len 까지 못 받음
int len = _buf[4];
int frameLen = 5 + len + 2;
if (_buf.Count < frameLen) break; // 프레임 미완성
var frame = _buf.GetRange(0, frameLen).ToArray();
_buf.RemoveRange(0, frameLen);
result.Add(frame);
}
return result;
}
private int FindSync()
{
for (int i = 0; i + 1 < _buf.Count; i++)
if (_buf[i] == Cvnet.Header && _buf[i + 1] == Cvnet.Device)
return i;
// 마지막 바이트가 Header 면 다음 바이트 대기
if (_buf.Count > 0 && _buf[^1] == Cvnet.Header) return _buf.Count - 1;
return -1;
}
public void Clear() => _buf.Clear();
}