2016-07-28 11 views
0

Ich nehme einen Blick auf die Netzwerkseite von Go und dachte, ich würde mit einem TCP-Client und -Server beginnen .Golang TCP Client empfängt keine Daten vom Server, hängt/blockiert auf conn.Read()

Ich bin in der Lage, den Client eine Verbindung zum Server herzustellen und eine einfache Nachricht ("Hallo") erfolgreich zu senden. Ich kann den Server jedoch nicht dazu bringen, eine Antwort zurückzusenden (oder den Client dazu zu veranlassen, die Antwort zu lesen).

Hier ist der Code.

Server

Address := "localhost:9999" 
Addr, err := net.ResolveTCPAddr("tcp", Address) 
if err != nil { 
    log.Fatal(err) 
} 

listener, err := net.ListenTCP("tcp", Addr) 
if err != nil { 
    log.Fatal(err) 
} 
defer listener.Close() 

//server loop 
for { 
    conn, err := listener.Accept() 
    if err != nil { 
     continue 
    } 

    go handle(conn) 
} 

func handle(c net.Conn) { 

    totalBytes, message := connRead(c) 
    fmt.Println(c.RemoteAddr()) 

    fmt.Println(string(message[:totalBytes])) 

    c.Write([]byte("Hi")) 
    fmt.Println("Replied") 
    c.Close() 
} 

func connRead(c net.Conn) (int, []byte) { 
    buffer := make([]byte, 4096) 
    totalBytes := 0 

    for { 
     n, err := c.Read(buffer) 
     totalBytes += n 
     if err != nil { 
      if err != io.EOF { 
       log.Printf("Read error: %s", err) 
      } 
      break 
     } 

    } 
    return totalBytes, buffer 
} 

Kunde

tcpAddr, err := net.ResolveTCPAddr("tcp", "localhost:9999") 
    if err != nil { 
     log.Fatal(err) 
    } 
    conn, err := net.DialTCP("tcp", nil, tcpAddr) 
    if err != nil { 
     log.Fatal(err) 
    } 
    defer conn.Close() 

    _, err = conn.Write([]byte("Hello")) 
    if err != nil { 
     log.Fatal(err) 
    } 

    tBytes, resp := connRead(conn) 
    fmt.Println(tBytes) 
    fmt.Println(string(resp[:tBytes])) 

func connRead(c net.Conn) (int, []byte) { 
    buffer := make([]byte, 4096) 
    totalBytes := 0 

    for { 
     fmt.Println("Stuck?") 
     n, err := c.Read(buffer) 
     fmt.Println("Stuck.") 
     totalBytes += n 
     fmt.Println(totalBytes) 
     if err != nil { 
      if err != io.EOF { 
       log.Printf("Read error: %s", err) 
      } 
      break 
     } 

    } 
    return totalBytes, buffer 
} 

Von dem, was ich, es ist nicht ein Problem mit dem Server berichten. Wenn ich den Client starte, stoppt alles nach fmt.Println("Stuck?"). Dies führt dazu, dass ich glaube, dass es in der n, err := c.Read(buffer) Aussage irgendwie versaut ist. Der Server druckt nicht einmal die Länge der Nachricht (5) und die Nachricht ("Hallo") aus, bevor ich den Client mit Ctrl-C verbunden habe. Wenn ich das Lesen und Drucken im Client auskommentiere, läuft alles reibungslos.

Ich habe versucht, nach Antworten zu googeln, aber nichts ist aufgetaucht.

Was mache ich falsch? Verwende ich conn.Read() falsch im Client?

EDIT:

ich tatsächlich den Zugriff auf Linux haben, so sind hier die SIGQUIT für die relevanten Funktionen Dumps.

Server

http://pastebin.com/itevngCq

Kunde

http://pastebin.com/XLiKqkvs

+1

Bei einem schnell lesen Blick, es sieht aus wie Client und Server blockieren EOF auf der Verbindung zu lesen. Senden SIQUIT an die laufenden Anwendungen, um herauszufinden, wo sie blockiert haben. –

+0

Ich bin auf Win 7, die SIGQUIT nicht unterstützt. – JimDoe

+0

Beide Programme sind beim Lesen blockiert. Einer oder beide Peers sollten [die Schreibseite schließen] (https://godoc.org/net#TCPConn.CloseWrite) der Verbindung, um den anderen Peer zu entsperren. Alternativ können Sie nach dem Lesen einer vollständigen Nachricht Nachrichtenrahmen hinzufügen und das Lesen stoppen. –

Antwort

1
for { 
    n, err := c.Read(buffer) 
    totalBytes += n 
    if err != nil { 
     if err != io.EOF { 
      log.Printf("Read error: %s", err) 
     } 
     break 
    } 

} 

Es ist, weil Sie von der Verbindung bis EOF Fehler lesen tritt

conn.Write([]byte("Hello")) 

Die obige Aussage EOF nicht erreichen wird überhaupt, bis Sie tatsächlich die Anschlussseite

Auf Drücken von Strg + c-Client schließen die Verbindung geschlossen wird, also EOF tritt auf Server-Seite, das ist der Grund, warum es verlässt Server-Seite für Schleife und Drucken diese

127.0.0.1:**** 
Hello 
Replied 

Wenn Sie diese Arbeit machen wollen, sollten Sie nicht die Verbindung bis EOF lesen

es gibt viele andere alternat ies dafür

  1. Wählen Sie ein Trennzeichen und lesen Sie auf dem Server, bis das Trennzeichen auftritt, und antworten Sie danach.Sehen Sie sich diese link
  2. Senden Anzahl von Bytes von Client-Seite zu lesen, bevor die eigentliche Nachricht zu senden, lesen Sie zuerst Anzahl von Bytes von der Server-Seite zu lesen und dann diese viele Bytes aus der Verbindung
+0

Danke. Ich entschied mich, mit alternativer Nummer 1 zu gehen. Wenn ich jetzt versuche, eine andere Nachricht vom selben Client zu senden, nachdem ich eine Antwort vom Server erhalte, scheint der Server die zweite Nachricht nicht zu bekommen. – JimDoe

+0

@JimDoe Können Sie die Quelle teilen, was Sie geschrieben haben, So dass ich Ihnen helfen kann – Raghu

+0

Natürlich! Auftraggeber: http://pastebin.com/k3B0zuVr Server: http://pastebin.com/9AXXjVwx Die zweite Nachricht sendet. Aber ich bekomme null Bytes vom Server zurück. – JimDoe