我有一个TCP服务器在无限循环中侦听请求:
use std::io::prelude::*;
use std::net::TcpStream;
use std::net::TcpListener;
fn main() {
let listener = TcpListener::bind("0.0.0.0:7878").unwrap();
for stream in listener.incoming() {
let mut stream = stream.unwrap();
let response = "HTTP/1.1 200 OK\r\n\r\nsdfuhgsjdfghsdfjk";
stream.write(response.as_bytes()).unwrap();
stream.flush().unwrap();
}
}
如何在一段时间(超时)后中断循环?
超时后,我需要停止监听循环:
答案 0 :(得分:0)
我认为您的问题与this一个问题有关。
但是由于您不是尝试将其与tokio
一起使用,而是与std
库和for循环一起使用,因此您需要通过其他线程进行管理。
您需要拥有
listener.incoming()
的连接作为非阻塞线程mpsc::channels()
,以便在这些线程之间传递数据。借助通道,您可以通知发生超时的时间,并在接受新连接时重置超时。
由于TcpListener
默认为阻止状态,因此您需要使用以下命令将其更改为非阻止状态:
let listener = TcpListener::bind("0.0.0.0:7878").unwrap();
listener
.set_nonblocking(true)
.expect("Could not set non blocking");
您可能会像下面这样糟透了:
use std::io::prelude::*;
use std::net::TcpListener;
use std::sync::mpsc::channel;
use std::thread;
use std::time::Duration;
fn main() {
let listener = TcpListener::bind("0.0.0.0:7878").unwrap();
listener
.set_nonblocking(true)
.expect("set_nonblocking call failed");
let (main_sender, main_receiver) = channel();
let main_sender_for_timeout_thread = main_sender.clone();
let main_sender_for_server_thread = main_sender.clone();
let (main_bus_sender, main_bus_receiver) = channel();
let main_bus_sender_for_timeout_thread = main_bus_sender.clone();
let main_bus_sender_for_server_thread = main_bus_sender.clone();
let timeout_thread = thread::spawn(move || {
let (timeout_sender, timeout_receiver) = channel();
let _ = main_bus_sender_for_timeout_thread.send(timeout_sender);
let mut current_timer = 0;
loop {
if current_timer == 10 {
let _ = main_sender_for_timeout_thread.send("TimeoutOccurred");
break;
}
println!(
"Waiting for timeout. Current Timer Count: {}",
current_timer
);
if timeout_receiver.try_recv().is_ok() {
//Reset timer
current_timer = 0;
}
let one_sec = Duration::new(1, 0);
thread::sleep(one_sec);
current_timer += 1;
}
});
let timeout_sender = main_bus_receiver.recv().unwrap();
let server_thread = thread::spawn(move || {
let (server_sender, server_receiver) = channel();
let _ = main_bus_sender_for_server_thread.send(server_sender);
for stream in listener.incoming() {
if let Ok(mut stream) = stream {
println!("Connection Accepted");
let response = "HTTP/1.1 200 OK\r\n\r\nsdfuhgsjdfghsdfjk";
stream.write(response.as_bytes()).unwrap();
stream.flush().unwrap();
let _ = main_sender_for_server_thread.send("ResetTimeout");
}
if let Ok(msg) = server_receiver.try_recv() {
if msg == "CloseServer" {
println!("Closing the server thread");
break;
}
}
}
});
let server_sender = main_bus_receiver.recv().unwrap();
loop {
let message = main_receiver.recv().unwrap();
if message == "ResetTimeout" {
println!("Connection established, resetting timeout");
let _ = timeout_sender.send("");
}
if message == "TimeoutOccurred" {
println!("TimeoutOccurred");
let _ = server_sender.send("CloseServer"); // This message closes the server
break;
}
}
let _ = timeout_thread.join();
}
请注意,最好使用incoming as future stream
和futures::mpsc()
在这些期货之间进行选择并适当地关闭。在我提供的示例中,您正在删除服务器线程而不是取消绑定它,这可以视为强制关闭。
有关使用期货板条箱的更好方法,您可以检查following