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

huangapple go评论71阅读模式
英文:

Read whole data with Golang net.Conn.Read

问题

所以我正在使用Go构建一个网络应用程序,我发现Conn.Read函数读取到一个有限的字节数组中,我使用make([]byte, 2048)创建了这个数组,但问题是我不知道内容的确切长度,所以可能太多或者不够。
我的问题是如何只读取到确切的数据量。我认为我需要使用bufio,但我不确定。

英文:

So I'm building a network app in Go and I've seen that Conn.Read reads into a limited byte array, which I had created with make([]byte, 2048) and now the problem is that I don't know the exact length of the content, so it could be too much or not enough.
My question is how can I just read the exact amount of data. I think I have to use bufio, but I'm not sure.

答案1

得分: 54

这取决于你想要做什么以及你期望的数据类型。例如,如果你只想读取直到文件结束符(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) // 大缓冲区
    tmp := make([]byte, 256)     // 使用小缓冲区进行演示
    for {
        n, err := conn.Read(tmp)
        if err != nil {
            if err != io.EOF {
                fmt.Println("read error:", err)
            }
            break
        }
        buf = append(buf, tmp[:n]...)
    }
    fmt.Println("total size:", len(buf))
}

// 编辑:为了完整起见和 @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())
}
英文:

It highly depends on what you're trying to do, and what kind of data you're expecting, for example if you just want to read until the EOF you could use something like this:

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: for completeness sake and @fabrizioM's great suggestion, which completely skipped my mind:

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())
}

答案2

得分: 40

你可以使用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)
}
英文:

You can use the ioutil.ReadAll function:

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)
}

答案3

得分: 7

你可以像这样读取数据:

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

....

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

defer Conn.Close()

for {
// 读取一行(以 \n 或 \r\n 结尾)
line, _ := tp.ReadLine()
// 在这里处理数据,拼接、处理等等...
}
....

英文:

You can read data something like this:

// 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... 
}
....

huangapple
  • 本文由 发表于 2014年6月21日 16:06:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/24339660.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定