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

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

Bug in golang google protocol buffer

问题

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

Python代码:

  1. Data = 0a300a084a6f686e20446f6510071a126a6f686e2e646f6540676d61696c2e636f6d220e0a0c3131312d3131312d31313130

Golang代码:

  1. 2016/04/02 23:21:08 50 bytes read from 192.168.0.1:65120
  2. 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....|
  3. 00000010 6a 6f 68 6e 2e 64 6f 65 40 67 6d 61 69 6c 2e 63 |john.doe@gmail.c|
  4. 00000020 6f 6d 22 0e 0a 0c 31 31 31 2d 31 31 31 2d 31 31 |om"...111-111-11|
  5. 00000030 31 30 |10|

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

  1. syntax = "proto3";
  2. package MC_Feed;
  3. message Person {
  4. enum PhoneType {
  5. MOBILE = 0;
  6. HOME = 1;
  7. WORK = 2;
  8. }
  9. string name = 1;
  10. int32 id = 2; // Unique ID number for this person.
  11. string email = 3;
  12. message PhoneNumber {
  13. string number = 1;
  14. PhoneType type = 2;
  15. }
  16. repeated PhoneNumber phones = 4;
  17. }
  18. // Our address book file is just one of these.
  19. message AddressBook {
  20. repeated Person people = 1;
  21. }

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

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

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

  1. package main
  2. import (
  3. "github.com/golang/protobuf/proto"
  4. "encoding/hex"
  5. "./Simple"
  6. "log"
  7. "net"
  8. )
  9. const (
  10. srvAddr = "239.0.0.222:345"
  11. maxDatagramSize = 8192
  12. )
  13. func main() {
  14. serveMulticastUDP(srvAddr, msgHandler)
  15. }
  16. func msgHandler(src *net.UDPAddr, n int, b []byte) {
  17. log.Println(n, "bytes read from", src)
  18. log.Println(hex.Dump(b[:n]))
  19. newTest := &MC_Feed.AddressBook{}
  20. err := proto.Unmarshal(b, newTest)
  21. log.Println(err)
  22. }
  23. func serveMulticastUDP(a string, h func(*net.UDPAddr, int, []byte)) {
  24. addr, err := net.ResolveUDPAddr("udp", a)
  25. if err != nil {
  26. log.Fatal(err)
  27. }
  28. l, err := net.ListenMulticastUDP("udp", nil, addr)
  29. l.SetReadBuffer(maxDatagramSize)
  30. for {
  31. b := make([]byte, maxDatagramSize)
  32. n, src, err := l.ReadFromUDP(b)
  33. if err != nil {
  34. log.Fatal("ReadFromUDP failed:", err)
  35. }
  36. h(src, n, b)
  37. }
  38. }
英文:

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

  1. python
  2. Data = 0a300a084a6f686e20446f6510071a126a6f686e2e646f6540676d61696c2e636f6d220e0a0c3131312d3131312d31313130
  3. golang
  4. 2016/04/02 23:21:08 50 bytes read from 192.168.0.1:65120
  5. 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....|
  6. 00000010 6a 6f 68 6e 2e 64 6f 65 40 67 6d 61 69 6c 2e 63 |john.doe@gmail.c|
  7. 00000020 6f 6d 22 0e 0a 0c 31 31 31 2d 31 31 31 2d 31 31 |om"...111-111-11|
  8. 00000030 31 30 |10|

The .proto file is identical in both.

  1. syntax = "proto3";
  2. package MC_Feed;
  3. message Person {
  4. enum PhoneType {
  5. MOBILE = 0;
  6. HOME = 1;
  7. WORK = 2;
  8. }
  9. string name = 1;
  10. int32 id = 2; // Unique ID number for this person.
  11. string email = 3;
  12. message PhoneNumber {
  13. string number = 1;
  14. PhoneType type = 2;
  15. }
  16. repeated PhoneNumber phones = 4;
  17. }
  18. // Our address book file is just one of these.
  19. message AddressBook {
  20. repeated Person people = 1;
  21. }

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

  1. 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:

  1. package main
  2. import (
  3. "github.com/golang/protobuf/proto"
  4. "encoding/hex"
  5. "./Simple"
  6. "log"
  7. "net"
  8. )
  9. const (
  10. srvAddr = "239.0.0.222:345"
  11. maxDatagramSize = 8192
  12. )
  13. func main() {
  14. serveMulticastUDP(srvAddr, msgHandler)
  15. }
  16. func msgHandler(src *net.UDPAddr, n int, b []byte) {
  17. log.Println(n, "bytes read from", src)
  18. log.Println(hex.Dump(b[:n]))
  19. newTest := &MC_Feed.AddressBook{}
  20. err := proto.Unmarshal(b, newTest)
  21. log.Println(err)
  22. }
  23. func serveMulticastUDP(a string, h func(*net.UDPAddr, int, []byte)) {
  24. addr, err := net.ResolveUDPAddr("udp", a)
  25. if err != nil {
  26. log.Fatal(err)
  27. }
  28. l, err := net.ListenMulticastUDP("udp", nil, addr)
  29. l.SetReadBuffer(maxDatagramSize)
  30. for {
  31. b := make([]byte, maxDatagramSize)
  32. n, src, err := l.ReadFromUDP(b)
  33. if err != nil {
  34. log.Fatal("ReadFromUDP failed:", err)
  35. }
  36. h(src, n, b)
  37. }
  38. }

答案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:

确定