使用Golang net.Conn.Read读取整个数据

use*_*892 20 go

所以我在Go中构建一个网络应用程序,我已经看到它Conn.Read读入了一个有限的字节数组,我创建了它make([]byte, 2048),现在的问题是我不知道内容的确切长度,所以它可能是太多或不够.
我的问题是如何才能读取确切的数据量.我想我必须使用bufio,但我不确定.

via*_*lly 32

你可以使用这个ioutil.ReadAll功能:

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)
}
Run Code Online (Sandbox Code Playgroud)

  • 两者,我都发现了它在我的特定情况下是什么,我试图读取 IMAP 连接上的所有响应,但是直到你自己关闭它才真正完成响应,所以它“挂起”(后来我正确读取行,直到我得到最终响应,然后停止读取更多行),但我将其粘贴到一个空白的新 .g​​o 文件中从未返回任何结果 (4认同)
  • 这个功能似乎对我来说挂死了,从来没有得到任何回应 (2认同)

One*_*One 31

它在很大程度上取决于你想要做什么,以及你期望什么样的数据,例如,如果你只想阅读直到EOF,你可以使用这样的东西:

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))
}
Run Code Online (Sandbox Code Playgroud)

//编辑:为了完整起见和@ fabrizioM的伟大建议,这完全忽略了我的想法:

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())
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您的读取循环获取“io.EOF”和非零“n”,则它可能不会打印出最后几个字节。根据“io.Reader”的文档,这可能会发生 (5认同)
  • 如果你想复制所有的内容,你也可以使用io.Copy(conn,NewBuffer) (3认同)
  • 我更喜欢您使用“tmp”缓冲区的第一种方法,您可以完全控制正在发生的事情。例如,它允许您处理通过连接传入的任何大小的输入,而无需冒“内存不足”错误的风险。 (2认同)

0xA*_*xAX 6

您可以像这样读取数据:

// 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... 
}
....
Run Code Online (Sandbox Code Playgroud)