namespace CvnetPacketProgram; /// /// 수신 바이트 스트림에서 0xF7 0x32 로 시작하는 완전한 프레임을 추출한다. /// 프레임 길이 = 5(Header~Len) + Len + 2(XOR,ADD). /// public sealed class FrameParser { private readonly List _buf = new(); public void Append(byte[] data, int len) { for (int i = 0; i < len; i++) _buf.Add(data[i]); } /// 버퍼에서 추출 가능한 모든 완전 프레임을 반환한다. public List Extract() { var result = new List(); 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(); }