linux - TcpStream 上的 std::io::BufReader 会导致数据丢失吗?
问题描述
当用于给定(字节)分隔符时,单个实例是否std::io::BufReader
会tokio::net::TcpStream
导致数据丢失?BufReader
read_until
也就是说,在我使用BufReader
for之后有没有可能:
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
将返回实际上超出分隔符 + 1 的数据,从而导致数据丢失?
我有一个问题(以及Linux 上完整的可重现示例),如果上述假设不正确,我很难解释。
我有一个 TCP 服务器,它应该在多个并发请求之后将文件的内容发送到多个 TCP 客户端。
有时,始终使用相同的输入,客户端接收到的数据少于预期,因此传输失败。
错误不会 100% 出现(也就是说,一些客户端请求仍然成功),但是在定义的 100 次尝试中tcp_client.rs
,至少其中一个总是可以重现的。
客户端和服务器之间传输的数据序列由以下部分组成:
- 客户端发送请求
- 服务器读取请求并发送响应
- 客户端读取响应
- 服务器发送文件数据
- 客户端读取文件数据
仅当涉及步骤 1、2 和 3 时,此问题才可重现,否则按预期工作。
当this tokio::io::read
(用于读取文件内容)返回0时报错,好像服务器关闭了连接,甚至服务器实际上已经启动并运行,并且所有数据都已发送(之后有一个断言tokio::io::copy
,我使用数据包嗅探器检查 TCP 数据包)。附带说明一下,在我的所有运行中,错误前读取的数据量总是比预期的多 95%。
最重要的是,该common.rs
模块定义了 2 个不同的read_*
功能:
read_until
目前使用。read_exact
不曾用过。
2 的逻辑是相同的,它们需要读取请求/响应(并且客户端和服务器都可以更新为使用其中一个)。令人惊讶的是,该错误仅在tokio::io::read_until
使用时才出现,而tokio::io::read_exact
按预期工作。
除非我误用tokio::io::read_until
了或我的实现中存在错误,否则我希望这两个版本都能正常工作。相反,我看到的是这种恐慌正在引发,因为某些客户端无法读取服务器发送的所有数据。
解决方案
是的。这在(强调我的)的文档中有所描述:BufReader
当
BufReader
被删除时,其缓冲区的内容将被丢弃。
下一句是正确的,但不够广泛:
BufReader
在同一流上创建多个实例可能会导致数据丢失。
BufReader
已从底层源读取数据并将其放入缓冲区,然后您已丢弃缓冲区。数据没了。
推荐阅读
- ios - 致命错误:无法从应用程序包中解码 productsTest.json
- node.js - 使用 nodejs 和 scoketio 发送实时通知
- python - ImportError:在 WINDOWS 上导入时 DLL 加载失败
- rabbitmq - 有没有办法为 Bitnami 上的 RabbitMQ 管理控制台启用 SSL?
- google-apps-script - 关于映射特定范围的googlesheet脚本问题
- ruby-on-rails - 如何使用带有自定义“get”路由的路径助手
- typescript - 如何在 Overlapping Marker Spiderfier for Leaflet 中应用特定的标记单击功能?
- swift - SwiftUI:@AppStorage 使用中的“属性初始化程序在'self'可用之前运行”
- excel - 如何使用只有一个特定单元格的范围方法?
- node.js - 测试页面上的文本