我在Rust中有一个TCP echo服务器随机丢弃消息。我试图在客户端套接字上设置读取超时。
客户端
use std::net::TcpStream;
use std::str;
use std::io::{self, BufRead, BufReader, Write};
use std::time::Duration;
use std::net::SocketAddr;
fn main() {
let remote: SocketAddr = "127.0.0.1:8888".parse().unwrap();
let mut stream = TcpStream::connect_timeout(&remote, Duration::from_secs(1)).expect("Could not connect to server");
stream.set_read_timeout(Some(Duration::from_millis(1))).expect("Could not set a read timeout");
loop {
let mut input = String::new();
let mut buffer: Vec<u8> = Vec::new();
io::stdin().read_line(&mut input).expect("Failed to read from stdin");
stream.write(input.as_bytes()).expect("Failed to write to server");
let mut reader = BufReader::new(&stream);
reader.read_until(b'\n', &mut buffer).expect("Could not read into buffer");
print!("{}", str::from_utf8(&buffer).expect("Could not write buffer as string"));
}
}
服务器
extern crate rand;
use std::net::{TcpListener, TcpStream};
use std::thread;
use rand::{thread_rng, Rng};
use std::io::{Error, Read, Write};
fn flip() -> bool {
let choices = [true, false];
let mut rng = thread_rng();
*rng.choose(&choices).unwrap()
}
fn handle_client(mut stream: TcpStream) -> Result<(), Error> {
let mut buf = [0; 512];
loop {
let bytes_read = stream.read(&mut buf)?;
if bytes_read == 0 {
return Ok(());
}
if flip() {
return Ok(());
}
stream.write(&buf[..bytes_read])?;
}
}
fn main() {
let listener = TcpListener::bind("127.0.0.1:8888").expect("Could not bind");
for stream in listener.incoming() {
match stream {
Err(e) => eprintln!("failed: {}", e),
Ok(stream) => {
thread::spawn(move || {
handle_client(stream).unwrap_or_else(|error| eprintln!("{:?}", error));
});
}
}
}
}
set_read_timeout
电话似乎没有做任何事情;即使我将持续时间设置为1毫秒,客户端仍会在服务器丢弃消息和中止连接之间等待几秒钟。
$ rustc tcp-client-timeout.rs && ./tcp-client-timeout
test
test
foo
foo
bar
thread 'main' panicked at 'Failed to write to server: Error { repr: Os { code: 32, message: "Broken pipe" } }', src/libcore/result.rs:906:4
note: Run with `RUST_BACKTRACE=1` for a backtrace.
答案 0 :(得分:1)
set_read_timeout
电话似乎没有做任何事情;客户端仍在服务器丢弃消息和中止连接之间等待几秒钟
这不是我运行代码的经验。事实上,当我在eprintln
调用之后直接添加read_until
时,它会在服务器决定放弃连接时立即打印。事实上,问题不在阅读中,而在于写,正如您从错误信息中可以看到的那样:
线程&#39;主要&#39;惊慌失措&#39; 无法写入服务器:
我猜你不是等了几秒钟,而是多次按 Enter (&#34之间的空行) ;栏&#34;以及恐慌信息也表明这一点)。您的读取超时工作正常 - 问题在于you are trying to write to a socket that the other side has already closed:
if flip() {
return Ok(());
}
退出循环,您将完全关闭套接字。您可以在客户端检测到这一点,也可以继续服务器循环而不是退出它。