Golang谷歌协议缓冲区中的错误。

huangapple go评论89阅读模式
英文:

Bug in golang google protocol buffer

问题

我有一个Python程序和一个Golang程序,都从一个socket获取数据。我打印出它们接收到的字节。

Python代码:

Data = 0a300a084a6f686e20446f6510071a126a6f686e2e646f6540676d61696c2e636f6d220e0a0c3131312d3131312d31313130

Golang代码:

2016/04/02 23:21:08 50 bytes read from 192.168.0.1:65120
2016/04/02 23:21:08 00000000  0a 30 0a 08 4a 6f 68 6e  20 44 6f 65 10 08 1a 12  |.0..John Doe....|
00000010  6a 6f 68 6e 2e 64 6f 65  40 67 6d 61 69 6c 2e 63  |john.doe@gmail.c|
00000020  6f 6d 22 0e 0a 0c 31 31  31 2d 31 31 31 2d 31 31  |om"...111-111-11|
00000030  31 30                                             |10|

.proto文件在两者中是相同的。

syntax = "proto3";
package MC_Feed;

message Person {
  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  string name = 1;
  int32 id = 2;  // Unique ID number for this person.
  string email = 3;

  message PhoneNumber {
    string number = 1;
    PhoneType type = 2;
  }

  repeated PhoneNumber phones = 4;
}

// Our address book file is just one of these.
message AddressBook {
  repeated Person people = 1;
}

在Python(以及C#)中,它可以正常工作。但在Golang方面,我得到了以下错误:

2016/04/02 23:21:08 proto: MC_Feed.AddressBook: illegal tag 0 (wire type 0)

这段Golang代码是我从网络上找到并稍作修改:

package main

import (
	"github.com/golang/protobuf/proto"
	"encoding/hex"
	"./Simple"
	"log"
	"net"
)

const (
	srvAddr         = "239.0.0.222:345"
	maxDatagramSize = 8192
)

func main() {
	serveMulticastUDP(srvAddr, msgHandler)
}


func msgHandler(src *net.UDPAddr, n int, b []byte) {
	log.Println(n, "bytes read from", src)
	log.Println(hex.Dump(b[:n]))
	newTest := &MC_Feed.AddressBook{}
    err := proto.Unmarshal(b, newTest)
    log.Println(err)
}

func serveMulticastUDP(a string, h func(*net.UDPAddr, int, []byte)) {
	addr, err := net.ResolveUDPAddr("udp", a)
	if err != nil {
		log.Fatal(err)
	}
	l, err := net.ListenMulticastUDP("udp", nil, addr)
	l.SetReadBuffer(maxDatagramSize)
	for {
		b := make([]byte, maxDatagramSize)
		n, src, err := l.ReadFromUDP(b)
		if err != nil {
			log.Fatal("ReadFromUDP failed:", err)
		}
		h(src, n, b)
	}
}
英文:

I have a python program and a golang program both getting data from a socket. I print the bytes it receives from both.

python

Data = 0a300a084a6f686e20446f6510071a126a6f686e2e646f6540676d61696c2e636f6d220e0a0c3131312d3131312d31313130

golang

2016/04/02 23:21:08 50 bytes read from 192.168.0.1:65120
2016/04/02 23:21:08 00000000  0a 30 0a 08 4a 6f 68 6e  20 44 6f 65 10 08 1a 12  |.0..John Doe....|
00000010  6a 6f 68 6e 2e 64 6f 65  40 67 6d 61 69 6c 2e 63  |john.doe@gmail.c|
00000020  6f 6d 22 0e 0a 0c 31 31  31 2d 31 31 31 2d 31 31  |om"...111-111-11|
00000030  31 30                                             |10|

The .proto file is identical in both.

syntax = "proto3";
package MC_Feed;

message Person {
  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  string name = 1;
  int32 id = 2;  // Unique ID number for this person.
  string email = 3;

  message PhoneNumber {
    string number = 1;
    PhoneType type = 2;
  }

  repeated PhoneNumber phones = 4;
}

// Our address book file is just one of these.
message AddressBook {
  repeated Person people = 1;
}

On the python (and C# for that matter) it works fine. On the golang side, I get this error:

2016/04/02 23:21:08 proto: MC_Feed.AddressBook: illegal tag 0 (wire type 0)

The go code is something I got from the net and modified a little:

package main

import (
	"github.com/golang/protobuf/proto"
	"encoding/hex"
	"./Simple"
	"log"
	"net"
)

const (
	srvAddr         = "239.0.0.222:345"
	maxDatagramSize = 8192
)

func main() {
	serveMulticastUDP(srvAddr, msgHandler)
}


func msgHandler(src *net.UDPAddr, n int, b []byte) {
	log.Println(n, "bytes read from", src)
	log.Println(hex.Dump(b[:n]))
	newTest := &MC_Feed.AddressBook{}
    err := proto.Unmarshal(b, newTest)
    log.Println(err)
}

func serveMulticastUDP(a string, h func(*net.UDPAddr, int, []byte)) {
	addr, err := net.ResolveUDPAddr("udp", a)
	if err != nil {
		log.Fatal(err)
	}
	l, err := net.ListenMulticastUDP("udp", nil, addr)
	l.SetReadBuffer(maxDatagramSize)
	for {
		b := make([]byte, maxDatagramSize)
		n, src, err := l.ReadFromUDP(b)
		if err != nil {
			log.Fatal("ReadFromUDP failed:", err)
		}
		h(src, n, b)
	}
}

答案1

得分: 6

您的缓冲区 b 的大小适合最大可能的数据报包,但其中并不全是您的消息,只有前 n 个字节是消息的一部分。关于 illegal tag 0wire type 0 的错误是由于尝试解析您未初始化的缓冲区空间中的 0 字节而引起的。将 b[:n] 传递给 Unmarshal 函数以修复该问题。

英文:

Your buffer b is sized for the maximum possible datagram packet but not all of that is your message, only the first n bytes. The messages about illegal tag 0 and wire type 0 result from trying to parse the 0 bytes in buffer space you haven't otherwise initialized. Pass b[:n] to Unmarshal to fix.

huangapple
  • 本文由 发表于 2016年4月3日 11:26:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/36381301.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定