2014-06-21 4 views
9

So ein Netzwerk App in Go Ich baue und ich habe gesehen, dass Conn.Read liest in einem begrenzten Byte-Array, das ich mit make([]byte, 2048) und jetzt das Problem geschaffen hatte, ist dass ich die genaue Länge des Inhalts nicht kenne, also könnte es zu viel oder zu wenig sein.
Meine Frage ist, wie kann ich gerade die genaue Menge an Daten lesen. Ich denke, ich muss bufio verwenden, aber ich bin mir nicht sicher.Lesen gesamten Daten mit Golang net.Conn.Read

+0

uns zeigen, welche Art von Daten Sie versuchen, es zu lesen, sonst nur ein Schuss im Dunkeln. – OneOfOne

Antwort

17

Es hängt stark ab, was Sie zu tun versuchen, und welche Art von Daten Sie erwarten, zum Beispiel, wenn Sie nur lesen wollen, bis die EOF könnten Sie so etwas wie folgt verwenden:

func main() { 
    conn, err := net.Dial("tcp", "google.com:80") 
    if err != nil { 
     fmt.Println("dial error:", err) 
     return 
    } 
    defer conn.Close() 
    fmt.Fprintf(conn, "GET/HTTP/1.0\r\n\r\n") 

    buf := make([]byte, 0, 4096) // big buffer 
    tmp := make([]byte, 256)  // using small tmo buffer for demonstrating 
    for { 
     n, err := conn.Read(tmp) 
     if err != nil { 
      if err != io.EOF { 
       fmt.Println("read error:", err) 
      } 
      break 
     } 
     //fmt.Println("got", n, "bytes.") 
     buf = append(buf, tmp[:n]...) 

    } 
    fmt.Println("total size:", len(buf)) 
    //fmt.Println(string(buf)) 
} 

// edit: der Vollständigkeit halber und @ fabrizioM der großen Vorschlag, die völlig meiner Meinung nach übersprungen:

func main() { 
    conn, err := net.Dial("tcp", "google.com:80") 
    if err != nil { 
     fmt.Println("dial error:", err) 
     return 
    } 
    defer conn.Close() 
    fmt.Fprintf(conn, "GET/HTTP/1.0\r\n\r\n") 
    var buf bytes.Buffer 
    io.Copy(&buf, conn) 
    fmt.Println("total size:", buf.Len()) 
} 
+1

Danke, ich habe darüber nachgedacht (Python socket.recv), aber ich bin irgendwie ein Anfänger in Go, also wusste ich nicht, wie man es implementiert. – user2563892

+3

Wenn Sie den gesamten Inhalt kopieren möchten, könnten Sie auch io.Copy (conn, NewBuffer) verwenden – fabrizioM

+0

Mein Verständnis ist, dass conn.Read (buf) blockiert und wird entweder die volle Länge des Puffers, wenn möglich, oder nach oben lesen zum Punkt eines EOF, an welchem ​​Punkt n verschieden von cap (buf) ist - aber möglicherweise dasselbe wie len (buf), wenn es mit 3 args deklariert wurde. Ist das korrekt? – CoolAJ86

2

Sie können Daten in etwa so lauten:

// import net/textproto 
import ("net/textproto", ...) 

.... 

reader := bufio.NewReader(Conn) 
tp := textproto.NewReader(reader) 

defer Conn.Close() 

for { 
    // read one line (ended with \n or \r\n) 
    line, _ := tp.ReadLine() 
    // do something with data here, concat, handle and etc... 
} 
.... 
+0

Gibt es dafür keinen effizienteren Weg? Und gibt es einen Weg, auf dem ich keine Endlosschleife benutzen muss? – user2563892

15

können Sie verwenden, um die ioutil.ReadAll Funktion:

import (
    "fmt" 
    "io/ioutil" 
    "net" 
) 

func whois(domain, server string) ([]byte, error) { 
    conn, err := net.Dial("tcp", server+":43") 
    if err != nil { 
     return nil, err 
    } 
    defer conn.Close() 

    fmt.Fprintf(conn, "%s\r\n", domain) 
    return ioutil.ReadAll(conn) 
} 
+0

Dies ist die richtige Antwort –