3 rust
我为网络服务器做了一个循环。在 Windows 客户端上我没有遇到任何问题,但在 Linux 客户端上服务器没有响应请求。
问题:我发现 if request_size % buffer_size == 0
then 循环再次运行以等待更多数据。
问题:是否有一种有效的方法来读取数据,同时考虑到慢速连接和丢包的连接。(不仅仅是使用 non_blocking 或 nodelay。)
let listener = TcpListener::bind("127.0.0.1:80").unwrap();
while let Ok((mut stream, _)) = listener.accept() {
let mut data: Vec<u8> = Vec::new();
let mut buf = [0u8; 32];
while let Ok(size) = stream.read(&mut buf) {
data.extend(buf[..size].iter());
if size != buf.len() { break; }
}
// do something with the data
}
Run Code Online (Sandbox Code Playgroud)
我可以增加缓冲区大小,但这并不能解决问题。
首先,为了可靠地检测 EOF,您应该测试返回size
的Read::read
零而不是缓冲区大小,因为如果您有“慢速连接”,您可能无法立即获得足够的数据来填充整个缓冲区,从而导致循环过早中的消息不完整data
。
基本上有 3 种方法可以确保您收到完整的消息:
请注意,只有最后两个变体允许您的客户端最终通过同一流发送更多数据。另请注意,这两种变体可以通过相对容易地实现Read::read_exact
。
另外请注意,如果您不信任您的客户端,设置TcpStream::set_read_timeout
相当长的超时(例如 2 分钟)可能会有所帮助。
这可能是最简单的,根据您的标题和代码,这可能是您想要的方法。然而,要生成 EOF,客户端必须至少关闭其写入通道。因此,如果您的服务器陷入困境read
,我假设您忘记关闭客户端(我必须在这里猜测)。
在服务器端,如果您确实想读取直到EOF,则不需要自己循环,只需使用Read::read_to_end
实用程序函数即可。以下是客户端和服务器的示例,其中客户端发送一条以EOF 终止的消息:
use std::io::Read;
use std::io::Write;
use std::net::TcpListener;
use std::net::TcpStream;
// --- Client code
const SERVER_ADDR: &str = "localhost:1234";
pub fn client() {
let mut socket = TcpStream::connect(SERVER_ADDR).expect("Failed to connect");
// Send a 'single' message, the flushes kinda simulates a very slow connection
for _ in 0..3 {
socket.write(b"Hello").expect("Failed to send");
socket.flush().unwrap();
}
// Instead of shutdow, you can also drop(socket), but than you can't read.
socket.shutdown(std::net::Shutdown::Write).unwrap();
// go reading, or whatever
}
// --- Server code
const SERVER_BIND: &str = "127.0.0.1:1234";
pub fn server() {
let listener = TcpListener::bind(SERVER_BIND).expect("Failed to bind");
while let Ok((stream, _)) = listener.accept() {
let _ = handle_client(stream); // don't care if the client screwed up
}
}
pub fn handle_client(mut socket: TcpStream) -> std::io::Result<()> {
let mut data: Vec<u8> = Vec::new();
// Read all bytes until EOF
socket.read_to_end(&mut data)?;
println!("Data: {:?}", data); // or whatever
Ok(())
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1528 次 |
最近记录: |