-
Flatbuffers로 만들어진 바이너리 식별 방법프로그래밍/의문 2021. 5. 10. 01:58반응형
결론: flatbuffers 바이너리에 헤더를 붙여서 쓰자.
플랫버퍼 바이너리는 바이너리 자신이 무엇인지 설명하지 않음. 즉, 플랫버퍼로 어떤 메세지를 직렬화 했을 때 이 직렬화된 메세지를 어떤식으로 해석해야 할 지 알 수 없다.
file identifier
파일 확장자처럼, 플랫버퍼 바이너리를 어떤식으로 해석해야 하는지 플랫버퍼 바이너리에 identifier를 기입할 수 있다. identifier를 기입하려면 FlatBufferBuilder::Finish 또는 FlatBufferBuilder::FinishSizePrefixed 함수에 identifier를 입력한다.
Finish에 fire_identifier 파라미터 단 identifier의 길이에는 제약이 있는데, 정확하게 4글자여야 한다는 것이다.
identifire 길이 제약 그리고 identifier를 이용한 바이너리는 flatbuffers::BufferHasIdentifier 함수로 Identifier가 있는지 여부 조회가 가능하며, flatbuffers::GetBufferIdentifier를 이용해 identifier를 가져올 수 있다. 따라서 이 방식은 flatbuffers로 만들어진 바이너리를 파일로 사용하기에 적합하다.
prefixed size
flatbuffers로 만들어진 바이너리 앞 단에 버퍼 사이즈를 기록하는 기능이다. 이 기능을 이용하려면 FlatBuferBuilder::Finish 대신 FlatBufferBuilder::FinishSizePrefixed를 이용한다.
GetPrefixedSize는 버퍼의 시작 위치에서 uoffset_t 사이즈를 읽어온다.
uoffset_t의 설명을 봐서는 항상 32bit임을 보장한다. 따라서 FinishSizePrefixed를 사용해서 flatbuffers 바이너리를 만들었다면, 첫 4바이트를 읽으면 필요 바이너리의 크기를 알 수 있다는 것이다.
union
여러 메세지 타입을 flatbuffer로 보낼 수 있는 기능이다. union을 이용하면 타입이 구분할 수 있는 네트워크 메세지를 보낼 수도 있으며, 그리고 oop의 다형성을 이용한 듯한 필드도 정의할 수 있다.
위와 같이 스키마를 정의하면 Message의 message 안에 Login2Req또는 Logout2Req를 담을 수 있다.
그리고 message의 메세지 타입을 읽고, 그 타입에 따라 캐스팅해서 읽어오는 식으로 사용할 수 있을 듯.
모호한 부분
바이너리의 필요 최소 사이즈를 4바이트로 간주해도 괜찮을지 모르겠다. 이 부분이 flatbuffers 제작자가 의도한 사용이라면 바이너리와 바이너리 크기를 받아 필요한 바이너리 사이즈를 반환하는 함수를 만들었을 거 같은데 없다. 즉, 첫 4바이트로 필요 바이트 수를 읽어오는 의도하지 않은 사용 방식일 수도 있다는 생각을 함.
네트워크 통신을 위해 flatbuffers를 사용하면 여러가지 메세지 타입이 있을 거다. 이 메세지들을 union MessageBase로 묶어 다양한 메세지들을 담게 하는 게 좋을지, 메세지마다 root_type으로 만들어서 쓰는 게 좋을지 잘 모르겠다. 이 부분은 알게 되면 여기에 내용을 보충할 것. 글을 쓰면서 드는 생각인데, c c++에서의 union처럼 메세지 내에서 가장 큰 사이즈로 크기가 잡히는 형태라면 메세지를 union으로 묶어서 쓰는 형식보다는, 메세지마다 root_type으로 써야한다. 나중에 확인해봐야지.
반응형'프로그래밍 > 의문' 카테고리의 다른 글
텅 빈 클래스 또는 구조체는 왜 0 사이즈가 아닐까? (0) 2021.10.23 UE4 데디케이티드 서버 만들기 샘플 (0) 2021.05.29 깃허브(Github) 계정으로 연동해 만든 깃랩(Gitlab) 계정으로 인증하기. (0) 2021.04.03 신기한 Unity Engine의 Destroy (0) 2020.12.13 [UE4]월드에 Player Start Actor가 있는데 Player Character가 스폰되지 않음 (0) 2020.09.15