【问题标题】:Serializing a struct to send it via UDP序列化结构以通过 UDP 发送它
【发布时间】:2019-04-18 19:50:42
【问题描述】:

我正在尝试弄清楚如何序列化结构并通过 UDP 将其发送到我的服务器。我设法实际发送了该结构,但收到后我没有任何值......除非我静态添加一个数字。

在下面的代码中,我向端口 8080 发送了一个 UDP 数据包,其序列号是 0-9 之间的数字。我在其中添加 + 1 以表明我的观点。我期望的是在接收端我应该在消息部分 1-10 中收到。但我收到的唯一信息是数字 1,这意味着该变量应设置为 0。

为了验证我是否真的发送了 0,我打印了我收到的缓冲区的长度,它应该是正确的长度。所以我一定是在解码方面做错了。

发送函数:

func send_udp() {
    dst, _ := net.ResolveUDPAddr("udp", "localhost:8080")
    conn, _ := net.ListenPacket("udp", ":0")
    defer conn.Close()

    var buf bytes.Buffer
    encoder := gob.NewEncoder(&buf)
    for n := 0; n < 10; n++ {
        var msg int64 = int64(n) + 1
        packet := &Packet{[]int{5}, msg}
        encoder.Encode(packet)
        conn.WriteTo(buf.Bytes(), dst)
    }
}

监听函数:

func listen_udp() {
    dst, _ := net.ResolveUDPAddr("udp", "localhost:8080")
    conn, _ := net.ListenUDP("udp", dst)
    defer conn.Close()

    for {
        buf := make([]byte, 4096)
        n, _, _ := conn.ReadFromUDP(buf[:])
        fmt.Println(n)
        dec := gob.NewDecoder(bytes.NewReader(buf[:n]))
        p := Packet{}
        dec.Decode(&p)
        if len(p.Parts) != 0 {
            fmt.Printf("Received: %+v\n", p)
        }
    }
}

我要发送的结构:

type Packet struct {
    Parts   []int 
    Message int64 
}

【问题讨论】:

  • 您忽略了示例中的所有错误值(写入、读取、编码、解码等);你检查过他们的线索吗? (这里也没有理由使用[:],我不确定你认为这是在做什么)
  • [:] 在 python 中用于复制切片。在 python 中,当你对数组进行切片时,它首先复制所有内容。在 go 中,每个切片仍然引用原始数组,因此什么都不买。

标签: go gob


【解决方案1】:

在我的本地机器上实现了这个。是的,请检查您的错误,但幸运的是,没有任何返回。这是我为解决问题所做的。在send_udp 中初始化BufferEncoder INSIDE for 循环。

func send_udp() error {
    dst, err := net.ResolveUDPAddr("udp", "localhost:8080")
    if err != nil {
        return err
    }
    conn, err := net.ListenPacket("udp", ":0")
    if err != nil {
        return err
    }
    defer conn.Close()

    for n := 0; n < 10; n++ {
        // inside for loop
        var buf bytes.Buffer
        encoder := gob.NewEncoder(&buf)

        var msg int64 = int64(n) + 1
        packet := &Packet{[]int{5}, msg}
        err = encoder.Encode(packet)
        if err != nil {
            return err
        }
        _, err = conn.WriteTo(buf.Bytes(), dst)
        if err != nil {
            return err
        }
    }
    return nil
}

请注意,在 for 循环之外声明 Buffer,实际上每次添加一个新 Packet 时都会发送一次,因此当您在listen_udp 函数,但每次只解码第一个。因此,如果您打算一次发送它们,则必须在 listen_udp 函数中循环遍历 Decoder

【讨论】:

  • 对不起吓到大家了。我的代码确实有错误检查,但我没有在此处发布它,因为我认为它与代码无关。下次我提出问题时,我会记得在代码中保留错误检查。感谢您轻松修复。
  • @FabioOesch:另一种选择是使用 // NOTE: error checking code here 之类的 cmets 注释您的示例代码,这样社区就知道您正在检查它们,但不会影响代码的意图。
  • @FabioOesch 或者只是使用check(err) 之类的假装错误检查功能发布帖子,然后忽略该功能,因为它无关紧要。任何想要实现您的代码的人都可以编写一个简单的函数,如果 err 不是 nil 就会发生恐慌。让愿意这样做的人更容易让您的 MVP 启动并运行以对其进行测试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-18
  • 2011-06-10
  • 1970-01-01
  • 2021-07-06
  • 1970-01-01
相关资源
最近更新 更多