英文:
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...
}
....
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论