gpt4 book ai didi

tcp - 在Tokio中使用TcpStream读取碎片化的TCP数据包

转载 作者:行者123 更新时间:2023-12-03 11:43:17 26 4
gpt4 key购买 nike

我在读取TCP数据包时遇到一些问题。

我正在尝试读取JSON响应,其大小为5000字节,但查看Wireshark中的数据包,它们被分为三个不同的数据包,第一个和第二个为1448字节,第三个为2530字节。

当我尝试使用Tokio-rs读取它们时,我只收到第一个,因此没有收到完整的JSON数据。

为了阅读,我使用以下代码:

pub async fn read(stream: &mut TcpStream) -> Result<Bytes, std::io::Error>{
let mut buf = BytesMut::with_capacity(8128);
let mut resp = [0u8; 8128];
let buf_len = stream.read(&mut resp).await?;
buf.extend_from_slice(&resp);
buf.truncate(buf_len);
println!("{}", buf.len());
Ok(buf.freeze())
}
buf.len()返回的 1448恰好是第一个和第二个数据包的大小,但是 buf包含来自第一个数据包的数据。

现在,我想知道是否丢失了某些内容,并且 TcpStream在第一个接收到的数据包关闭时还是在某处丢失了缓冲区大小。

最佳答案

诸如 Read::read AsyncReadExt::read 之类的读取方法通常不保证所有数据都会消耗多少。如果TcpStream具有三个可用数据包,则它可能仅消耗第一个数据包或前两个数据包,或者第一个数据包消耗第二个数据包的一半。无论执行什么操作,都是一个实现细节。您可以做的唯一假设是,如果它返回0(即未读取任何字节),则它已达到其“流末尾”(例如,由于连接已关闭)。

因此,通常应该循环阅读:

let mut buf = BytesMut::with_capacity(8128);
let mut resp = [0u8; 8128];

loop {
let buf_len = stream.read(&mut resp).await?;
buf.extend_from_slice(&resp[0..buf_len]);

if buf_len == 0 {
// end of stream
panic!("Unexpected EOF");
} else if buf.len() >= 5000 {
// ^---------------^
// \_________ some condition to check if buffer is "ready"

// buffer has been filled with enough bytes
break;
} else {
// buffer does not have enough bytes, keep reading...
continue;
}
}

println!("{}", buf.len());
Ok(buf.freeze())

或者,如果您想填满整个缓冲区,则可以改用 read_exact 方法,该方法将为您循环读取直到缓冲区已满,或者使用 read_to_end ,该方法将读取直到循环结束。

关于tcp - 在Tokio中使用TcpStream读取碎片化的TCP数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61293438/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com