为了账号安全,请及时绑定邮箱和手机立即绑定

TCP `net.Conn.Read` 在使用`encoding/gob` 解码器后挂起

TCP `net.Conn.Read` 在使用`encoding/gob` 解码器后挂起

Go
慕尼黑8549860 2022-01-10 17:26:26
我可以net.Conn用encoding/goben/decoder包装 TCP 的末端并通过它成功地 en/decode 一个值,但是如果我在原始连接上Decode使用 a Read,它会挂在Read:package mainimport (    "encoding/gob"    "net"    "log"    "sync")func main() {    var wg sync.WaitGroup    addr := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 9000}    ready := make(chan struct{})    wg.Add(1)    go func() {        defer wg.Done()        ln, err := net.ListenTCP("tcp4", addr)        if err != nil {            log.Fatal("ln: ", err)        }        defer ln.Close()        close(ready)        conn, err := ln.Accept()        if err != nil {            log.Fatal("conn: ", err)        }        defer conn.Close()        var out string        if err := gob.NewDecoder(conn).Decode(&out); err != nil {            log.Fatal("error decoding: ", err)        }        if "hello" != out {            log.Fatalf("1 expected '%s', got '%s'", "hello", out)        }        b := make([]byte, 1)        log.Println("ready to read 1")        if _, err := conn.Read(b); err != nil {            log.Fatal("error reading: ", err)        }        log.Println("read 1")        if b[0] != 1 {            log.Fatalf("2 expected '%d', got '%d'", 1, b[0])        }        if _, err := conn.Write([]byte{1}); err != nil {            log.Fatal("err writing2: ", err)        }        log.Println("done 1")    }()    wg.Add(1)    go func() {        defer wg.Done()        <-ready        conn, err := net.DialTCP("tcp4", nil, addr)        if err != nil {            log.Fatal("conn2: ", err)        }}输出:2009/11/10 23:00:00 waiting2009/11/10 23:00:00 ready to read 22009/11/10 23:00:00 ready to read 1这会在 Go Playground 中导致死锁恐慌并挂在我的本地机器上 ( go version go1.6.2 darwin/amd64),尽管代码会间歇性地在本地执行到完成。如果我使用 anet.PipeConn或者如果我Decode使用 aWrite来代替(即在 en/decode 之后交换Read/的顺序),则不会发生这种情况Write。当我删除 en/decode 代码时,en/decode 之后的代码也可以单独工作。是什么导致了这个挂起?这感觉像是一个缓存问题,但我不知道为什么Write不会刷新或为什么Read不会提取最新的可用数据,或者为什么这个问题只在gob涉及编码/解码时出现。
查看完整描述

1 回答

?
三国纷争

TA贡献1804条经验 获得超7个赞

gobbufio.Reader如果读者还不是 bufio,则将读者包装在 a 中,您确实有 2 个选项:

  1. 将您的 conn 包装在 bufio.Reader 中并将其传递给 gob 并从那时起使用它。

  2. 对所有东西都使用 gob,不要手动读/写。


查看完整回答
反对 回复 2022-01-10
  • 1 回答
  • 0 关注
  • 155 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信