Rust echo 服务器和客户端使用 futures 永远阻塞自己
Rust echo server and client using futures blocks itself forever
我使用 this code for the server, and modified this tutorial 作为客户端代码。当客户端连接到服务器时,它会永远阻塞自己。
服务器:
extern crate futures;
extern crate futures_io;
extern crate futures_mio;
use std::net::SocketAddr;
use futures::Future;
use futures_io::{copy, TaskIo};
use futures::stream::Stream;
fn main() {
let addr = "127.0.0.1:8080".parse::<SocketAddr>().unwrap();
let mut l = futures_mio::Loop::new().unwrap();
let server = l.handle().tcp_listen(&addr);
let done = server.and_then(move |socket| {
println!("Listening on: {}", addr);
socket.incoming().for_each(|(socket, addr)| {
let io = TaskIo::new(socket);
let pair = io.map(|io| io.split());
let amt = pair.and_then(|(reader, writer)| {
copy(reader, writer)
});
amt.map(move |amt| {
println!("wrote {} bytes to {}", amt, addr)
}).forget();
Ok(())
})
});
l.run(done).unwrap();
}
客户:
extern crate futures;
extern crate futures_io;
extern crate futures_mio;
use std::net::SocketAddr;
use futures::Future;
use futures_mio::Loop;
fn main() {
let mut lp = Loop::new().unwrap();
let addr = "127.0.0.1:8080".parse::<SocketAddr>().unwrap();
let socket = lp.handle().tcp_connect(&addr);
let request = socket.and_then(|socket| {
futures_io::write_all(socket, b"Hello!")
});
let response = request.and_then(|(socket, _)| {
futures_io::read_to_end(socket, Vec::new())
});
let data = lp.run(response).unwrap();
println!("{}", String::from_utf8_lossy(&data));
}
问题与期货无关。你有一个打开的套接字,你要求 "read it until the end"。 什么决定结束?在这种情况下,它是在套接字关闭时;那是什么时候?
骗人的问题!
- 客户端的读套接字在服务器的写套接字关闭时关闭。
- 当服务器的读套接字关闭时,服务器的写套接字也关闭。
- 当客户端的写套接字关闭时,服务器的读套接字也关闭。
那什么时候发生?因为没有专门的代码,所以当套接字被丢弃时它会关闭,所以:
- 客户端的写套接字在客户端结束时关闭。
于是陷入僵局。可以通过显式关闭套接字的写入部分来解决此问题:
let response = request.and_then(|(socket, _)| {
socket.shutdown(std::net::Shutdown::Write).expect("Couldn't shut down");
read_to_end(socket, Vec::new())
});
我使用 this code for the server, and modified this tutorial 作为客户端代码。当客户端连接到服务器时,它会永远阻塞自己。
服务器:
extern crate futures;
extern crate futures_io;
extern crate futures_mio;
use std::net::SocketAddr;
use futures::Future;
use futures_io::{copy, TaskIo};
use futures::stream::Stream;
fn main() {
let addr = "127.0.0.1:8080".parse::<SocketAddr>().unwrap();
let mut l = futures_mio::Loop::new().unwrap();
let server = l.handle().tcp_listen(&addr);
let done = server.and_then(move |socket| {
println!("Listening on: {}", addr);
socket.incoming().for_each(|(socket, addr)| {
let io = TaskIo::new(socket);
let pair = io.map(|io| io.split());
let amt = pair.and_then(|(reader, writer)| {
copy(reader, writer)
});
amt.map(move |amt| {
println!("wrote {} bytes to {}", amt, addr)
}).forget();
Ok(())
})
});
l.run(done).unwrap();
}
客户:
extern crate futures;
extern crate futures_io;
extern crate futures_mio;
use std::net::SocketAddr;
use futures::Future;
use futures_mio::Loop;
fn main() {
let mut lp = Loop::new().unwrap();
let addr = "127.0.0.1:8080".parse::<SocketAddr>().unwrap();
let socket = lp.handle().tcp_connect(&addr);
let request = socket.and_then(|socket| {
futures_io::write_all(socket, b"Hello!")
});
let response = request.and_then(|(socket, _)| {
futures_io::read_to_end(socket, Vec::new())
});
let data = lp.run(response).unwrap();
println!("{}", String::from_utf8_lossy(&data));
}
问题与期货无关。你有一个打开的套接字,你要求 "read it until the end"。 什么决定结束?在这种情况下,它是在套接字关闭时;那是什么时候?
骗人的问题!
- 客户端的读套接字在服务器的写套接字关闭时关闭。
- 当服务器的读套接字关闭时,服务器的写套接字也关闭。
- 当客户端的写套接字关闭时,服务器的读套接字也关闭。
那什么时候发生?因为没有专门的代码,所以当套接字被丢弃时它会关闭,所以:
- 客户端的写套接字在客户端结束时关闭。
于是陷入僵局。可以通过显式关闭套接字的写入部分来解决此问题:
let response = request.and_then(|(socket, _)| {
socket.shutdown(std::net::Shutdown::Write).expect("Couldn't shut down");
read_to_end(socket, Vec::new())
});