> 백엔드 개발 > Golang > 유형 정보 없이 알 수 없는 Protobuf 메시지를 어떻게 구문 분석할 수 있나요?

유형 정보 없이 알 수 없는 Protobuf 메시지를 어떻게 구문 분석할 수 있나요?

Patricia Arquette
풀어 주다: 2024-11-28 01:36:10
원래의
681명이 탐색했습니다.

How Can I Parse Unknown Protobuf Messages Without Type Information?

유형 정보 없이 알 수 없는 프로토 메시지 디마샬링

protobuf의 proto.Unmarshal() 메서드에는 알려진 메시지 유형이 필요하지만 알 수 없는 메시지에는 문제가 발생합니다. . 그러나 protowire 패키지를 사용하면 제한된 정보를 추출할 수 있습니다.

접근 방식:

  1. protowire.ConsumeField()를 사용하여 알 수 없는 메시지 페이로드를 반복합니다.
  2. 필드 유형을 식별합니다. be:

    • Varint
    • Fixed64
    • 바이트
    • StartGroup
    • Fixed32
  3. 다음을 기반으로 필드 페이로드를 구문 분석합니다. 해당 유형입니다.
  4. 페이로드를 재귀적으로 구문 분석하여 하위 메시지를 처리합니다.

데이터 모델:

type Field struct {
    Tag Tag
    Val Val
}

type Tag struct {
    Num int32
    Type protowire.Type
}

type Val struct {
    Payload interface{}
    Length int
}
로그인 후 복사

파서:

func parseUnknown(b []byte) []Field {
    // Iteratively consume and parse fields
    for len(b) > 0 {
        // Read field tag and length
        n, t, fieldlen := protowire.ConsumeField(b)
        if fieldlen < 1 {
            return nil
        }
        field := Field{Tag: Tag{Num: int32(n), Type: t}}

        // Read and process tag and value content
        _, _, taglen := protowire.ConsumeTag(b[:fieldlen])
        if taglen < 1 {
            return nil
        }
        var v interface{}
        var vlen int
        switch t {
            case protowire.VarintType:
                v, vlen = protowire.ConsumeVarint(b[taglen:fieldlen])
            case protowire.Fixed64Type:
                v, vlen = protowire.ConsumeFixed64(b[taglen:fieldlen])
            case protowire.BytesType:
                v, vlen = protowire.ConsumeBytes(b[taglen:fieldlen])
                sub := parseUnknown(v.([]byte))
                if sub != nil {
                    v = sub
                }
            case protowire.StartGroupType:
                v, vlen = protowire.ConsumeGroup(n, b[taglen:fieldlen])
                sub := parseUnknown(v.([]byte))
                if sub != nil {
                    v = sub
                }
            case protowire.Fixed32Type:
                v, vlen = protowire.ConsumeFixed32(b[taglen:fieldlen])
        }
        if vlen < 1 {
            return nil
        }

        field.Val = Val{Payload: v, Length: vlen - taglen}
        fields = append(fields, field)
        b = b[fieldlen:]
    }
    return fields
}
로그인 후 복사

예(메시지 구조):

message Foo {
  string a = 1;
  string b = 2;
  Bar bar = 3;
}

message Bar {
  string c = 1;
}
로그인 후 복사

예(파싱됨) 출력):

main.Field{Tag:main.Tag{Num:1, Type:2}, Val:main.Val{Payload:[]uint8{0x41}, Length:1}}
main.Field{Tag:main.Tag{Num:2, Type:2}, Val:main.Val{Payload:[]uint8{0x42}, Length:1}}
main.Field{Tag:main.Tag{Num:1, Type:2}, Val:main.Val{Payload:[]uint8{0x43}, Length:1}}
main.Field{Tag:main.Tag{Num:3, Type:2}, Val:main.Val{Payload:[]main.Field{main.Field{Tag:main.Tag{Num:1, Type:2}, Val:main.Val{Payload:[]uint8{0x43}, Length:1}}}, Length:3}}
로그인 후 복사

고려 사항:

  • 하위 메시지: 메시지로 식별된 바이트 페이로드의 재귀 구문 분석 .
  • 반복됨 fields: 동일한 필드 태그 번호를 기반으로 처리됩니다.
  • Maps: 반복되는 k/v 쌍과 유사한 것으로 가정됩니다.
  • Oneofs: Union 유형 정보는 사라지고 실제 값만 남습니다.

이 코드는 완전한 프로덕션급 솔루션을 제공하지는 않지만 일부 의미 정보를 보존하면서 알 수 없는 proto 페이로드를 구문 분석하는 방법을 제공합니다.

위 내용은 유형 정보 없이 알 수 없는 Protobuf 메시지를 어떻게 구문 분석할 수 있나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿