Ich kann die Enden eines TCP net.Conn
mit einem encoding/gob
de/decoder einwickeln und einen Wert damit erfolgreich decodieren/dekodieren, aber wenn ich folge die Decode
mit einem Read
auf der rohen Verbindung auf dem Read
hängt:TCP `net.Conn.Read` hängt nach der Verwendung eines` encoding/gob` Dekoders
package main
import (
"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)
}
defer conn.Close()
if err := gob.NewEncoder(conn).Encode("hello"); err != nil {
log.Fatal("error encoding: ", err)
}
if _, err := conn.Write([]byte{1}); err != nil {
log.Fatal("write error: ", err)
}
b := make([]byte, 1)
log.Println("ready to read 2")
if _, err := conn.Read(b); err != nil {
log.Fatal("error reading2: ", err)
}
log.Println("read 2")
if b[0] != 1 {
log.Fatalf("3 expected '%d', got '%d'", 1, b[0])
}
log.Println("done 2")
}()
log.Println("waiting")
wg.Wait()
log.Println("waited")
}
der Ausgang:
2009/11/10 23:00:00 waiting
2009/11/10 23:00:00 ready to read 2
2009/11/10 23:00:00 ready to read 1
Dieses eine deadlock panic im Go Spielplatz verursacht und hängt an meinem lokalen Rechner (0.123.), obwohl der Code zeitweise vollständig ausgeführt wird.
Dies geschieht nicht, wenn ich ein net.PipeConn
verwenden oder wenn ich die Decode
mit einem Write
stattdessen folgen (d tauscht die Reihenfolge der Read
/Write
nach dem de/dekodieren). Der Code nach dem en/decode funktioniert auch isoliert, wenn ich den en/decode entziehe.
Was verursacht diesen Hang? Dies fühlt sich an wie ein Caching-Problem, aber ich weiß nicht, warum die Write
nicht flush oder warum die Read
würde nicht die neuesten verfügbaren Daten ziehen, oder warum dieses Problem nur auftritt, wenn gob
en/Decodierung beteiligt ist.
Ah, ich glaube, ich verstehe, in unteren Begriffen gelesen der Puffer wahrscheinlich das zusätzliche Byte, das ich sendete? Vielen Dank für die Antwort! –