TcpStream 上的 std::io::BufReader 会导致数据丢失吗?

Can std::io::BufReader on a TcpStream lead to data loss?

std::io::BufReader on a tokio::net::TcpStream lead to data loss when the BufReader is used to read_until 的单个实例可以作为给定的(字节)定界符吗?

也就是说,有没有可能在我使用BufReader之后:

let buffer = Vec::new();
let reader = BufReader::new(tcp_stream);
tokio::io::read_until(reader, delimiter, buffer)
   .map(move |(s, _)| s.into_inner())

使用相同流的 tokio::io::read 之后的 return 数据实际上超出了分隔符 + 1,因此导致数据丢失?


我有一个问题(complete reproducible example on Linux),如果上述假设不正确,我无法解释。

我有一个 TCP 服务器,它应该在多个并发请求后将文件的内容发送到多个 TCP 客户端。

有时,始终使用相同的输入,客户端收到的数据少于预期,因此传输失败。

错误并非 100% 出现(也就是说,一些客户端请求仍然成功),但在 tcp_client.rs 中定义的 100 次尝试中,至少其中一次总是可重现的.

客户端和服务器之间传输的数据序列由以下组成:

  1. 客户端发送请求
  2. 服务器读取请求并发送响应
  3. 客户端读取响应
  4. 服务器发送文件数据
  5. 客户端读取文件数据

仅当涉及步骤 1、2 和 3 时,此问题才会重现,否则它会按预期工作。

当这个 tokio::io::read (used to read the file content) returns 0, as if the server closed the connection, even is the server is actually up and running, and all the data has been sent (there is an assertion after tokio::io::copy 并且我使用数据包嗅探器检查 TCP 数据包时会出现错误)。附带一提,在我所有的运行中,错误发生前读取的数据量总是比预期的多 95%。

最重要的是 common.rs 模块定义了 2 个不同的 read_* 函数:

2 的逻辑是相同的,他们需要读取 request/response (客户端和服务器都可以更新为使用一个或另一个)。令人惊讶的是,该错误仅在使用 tokio::io::read_until 时出现,而 tokio::io::read_exact 按预期工作。

除非我误用了 tokio::io::read_until 或者我的实现中存在错误,否则我希望这两个版本都能正常工作。我看到的是 this panic 被引发,因为一些客户端无法读取服务器发送的所有数据。

是的。 documentation for BufReader(强调我的)中对此进行了描述:

When the BufReader is dropped, the contents of its buffer will be discarded.

下一句正确但不够广泛:

Creating multiple instances of a BufReader on the same stream can cause data loss.

BufReader 已经从底层源中读取数据并将其放入缓冲区,那么您已经丢弃了缓冲区。数据没了