ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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으로 써야한다. 나중에 확인해봐야지.

    반응형
Designed by Tistory.