为什么 io.Copy 从套接字读取时有时会丢失行?
Why does io.Copy sometimes lose lines when reading from a socket?
请帮助我理解观察到的从套接字读取的行为。
在实验中,发送方总是发送相同的行,以'\n'结尾,然后关闭套接字的写端。
接收方的这段代码按预期工作,打印每一行:
rdr := bufio.NewReader(sock)
for {
b, err := rdr.ReadBytes('\n')
if err != nil {
break
}
fmt.Print(string(b))
}
但是,这段代码
n, err := io.Copy(os.Stdout, sock)
有时会从数据块的开头跳过随机数行,只打印其余部分(n
会相应变化,而 err
始终为 nil)。
sock
是一种自定义类型,它抽象了 net.TCPConn
和 tls.Conn
,否则将在整个代码库中使用 w/o 问题。
为什么 io.Copy
读取的开头的行有时会丢失?
bufio.Reader
implements buffering for an io.Reader
对象。这是什么意思?如果您使用 bufio.Reader
从 io.Reader
源读取,它可能会从其源读取(并缓冲)比您直接从 bufio.Reader
本身读取的数据更多的数据。
这意味着如果您先使用 bufio.Reader
从 sock
读取,然后使用 io.Copy()
,可能已经从 sock
读取了一些数据并坐在 bufio.Reader
的内部缓冲区中,io.Copy()
看不到也不会复制。
你不应该在同一个 io.Reader
源中混合这两个。如果必须,请务必先清空 bufio.Reader
的缓冲区,然后继续从 sock
复制,如下所示:
// First drain the buffer:
n, err := io.Copy(os.Stdout, rdr)
// Handle error
// Then proceed with the socket:
n, err = io.Copy(os.Stdout, sock)
// Handle error
请帮助我理解观察到的从套接字读取的行为。
在实验中,发送方总是发送相同的行,以'\n'结尾,然后关闭套接字的写端。
接收方的这段代码按预期工作,打印每一行:
rdr := bufio.NewReader(sock)
for {
b, err := rdr.ReadBytes('\n')
if err != nil {
break
}
fmt.Print(string(b))
}
但是,这段代码
n, err := io.Copy(os.Stdout, sock)
有时会从数据块的开头跳过随机数行,只打印其余部分(n
会相应变化,而 err
始终为 nil)。
sock
是一种自定义类型,它抽象了 net.TCPConn
和 tls.Conn
,否则将在整个代码库中使用 w/o 问题。
为什么 io.Copy
读取的开头的行有时会丢失?
bufio.Reader
implements buffering for an io.Reader
对象。这是什么意思?如果您使用 bufio.Reader
从 io.Reader
源读取,它可能会从其源读取(并缓冲)比您直接从 bufio.Reader
本身读取的数据更多的数据。
这意味着如果您先使用 bufio.Reader
从 sock
读取,然后使用 io.Copy()
,可能已经从 sock
读取了一些数据并坐在 bufio.Reader
的内部缓冲区中,io.Copy()
看不到也不会复制。
你不应该在同一个 io.Reader
源中混合这两个。如果必须,请务必先清空 bufio.Reader
的缓冲区,然后继续从 sock
复制,如下所示:
// First drain the buffer:
n, err := io.Copy(os.Stdout, rdr)
// Handle error
// Then proceed with the socket:
n, err = io.Copy(os.Stdout, sock)
// Handle error