英文:
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
始终为nil)。
n, err := io.Copy(os.Stdout, sock)
sock
是一个自定义类型,它封装了net.TCPConn
和tls.Conn
,在代码库中其他地方使用时没有问题。
为什么通过io.Copy
读取的开头行有时会丢失?
英文:
Please help me understand the observed behavior of reading from a socket.
In the experiment, the sender always sends the same lines, which end in '\n', then closes the write end of a socket.
This code on a receiving side works as expected, printing each line:
rdr := bufio.NewReader(sock)
for {
b, err := rdr.ReadBytes('\n')
if err != nil {
break
}
fmt.Print(string(b))
}
However, this code
n, err := io.Copy(os.Stdout, sock)
sometimes skips a random number of lines from the beginning of the data block, and only prints the rest (n
changes accordingly, and err
is always nil).
The sock
is a custom type, which abstracts net.TCPConn
and tls.Conn
, which is otherwise used throughout the codebase w/o problems.
Why lines at the beginning of the read by io.Copy
are sometimes lost?
答案1
得分: 1
bufio.Reader
实现了对 io.Reader
对象的缓冲。这是什么意思?如果你使用 bufio.Reader
从一个 io.Reader
源读取数据,它可能会从源中读取更多的数据(并将其缓存),而不仅仅是直接从 bufio.Reader
中读取的数据。
这意味着,如果你首先使用 bufio.Reader
从 sock
中读取数据,然后使用 io.Copy()
,那么可能已经有一些数据从 sock
中读取并存储在 bufio.Reader
的内部缓冲区中,而 io.Copy()
将无法看到并复制这些数据。
你不应该在同一个 io.Reader
源上混合使用它们。如果你必须这样做,那么请确保首先清空 bufio.Reader
的缓冲区,然后再从 sock
中复制数据,像这样:
// 首先清空缓冲区:
n, err := io.Copy(os.Stdout, rdr)
// 处理错误
// 然后继续处理 socket:
n, err = io.Copy(os.Stdout, sock)
// 处理错误
英文:
bufio.Reader
implements buffering for an io.Reader
object. What does this mean? If you use a bufio.Reader
to read from an io.Reader
source, it may read more data from its source (and buffer it) than what you read directly from the bufio.Reader
itself.
This means if you use a bufio.Reader
to read from the sock
first, and then you use io.Copy()
, there may be some data already read from sock
and sitting in the bufio.Reader
's internal buffer, which io.Copy()
will not see and will not copy.
You shouldn't mix those 2 on the same io.Reader
source. If you must, then be sure to first drain the bufio.Reader
's buffer, then proceed to copy from sock
like this:
// 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论