Server 使用futures的Rust echo服务器和客户端将永远阻塞自身

Server 使用futures的Rust echo服务器和客户端将永远阻塞自身,server,client,rust,echo,Server,Client,Rust,Echo,我为服务器使用,为客户端代码修改。当客户机连接到服务器时,它将永远阻塞自身 服务器: 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 add

我为服务器使用,为客户端代码修改。当客户机连接到服务器时,它将永远阻塞自身

服务器:

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));
}
extern板条箱期货;
外部板条箱期货;
外部板条箱期货;
使用std::net::SocketAddr;
使用期货:未来;
使用未来io::{copy,TaskIo};
使用futures::stream::stream;
fn main(){
让addr=“127.0.0.1:8080”。解析::()。展开();
让mut l=futures\u mio::Loop::new().unwrap();
让server=l.handle().tcp_侦听(&addr);
让done=server.and|u然后(移动|套接字|{
println!(“监听:{}”,地址);
socket.incoming()。用于每个(|(socket,addr)|{
让io=TaskIo::新建(套接字);
让pair=io.map(| io | io.split());
让amt=pair.u然后(|(读写器)|{
副本(读者、作者)
});
金额地图(移动|金额|{
println!(“将{}字节写入{}”,amt,addr)
}).忘记();
好(())
})
});
l、 运行(完成)。展开();
}
客户端:

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));
}
extern板条箱期货;
外部板条箱期货;
外部板条箱期货;
使用std::net::SocketAddr;
使用期货:未来;
使用futures_mio::Loop;
fn main(){
让mut lp=Loop::new().unwrap();
让addr=“127.0.0.1:8080”。解析::()。展开();
让socket=lp.handle().tcp_连接(&addr);
让request=socket.and|u然后(| socket |{
未来io::全部写入(套接字,b“你好!”)
});
让response=request.and然后(|(socket,|)|{
未来io::读取到末尾(套接字,Vec::新建())
});
让data=lp.run(response.unwrap();
println!(“{}”,String::from_utf8_lossy(&data));
}

这个问题与期货无关。你有一个打开的插座,你要求“读到最后”什么决定结束?在这种情况下,是插座关闭时;那是什么时候

骗人的问题

  • 当服务器的写套接字关闭时,客户端的读套接字关闭
  • 服务器的读套接字关闭时,服务器的写套接字关闭
  • 当客户端的写套接字关闭时,服务器的读套接字关闭
那什么时候会发生呢?由于没有专门执行此操作的代码,因此当套接字断开时,它将关闭,因此:

  • 客户端的写套接字在客户端结束时关闭
这样就打破了僵局。可以通过显式关闭套接字的写入部分来解决此问题:

let response = request.and_then(|(socket, _)| {
    socket.shutdown(std::net::Shutdown::Write).expect("Couldn't shut down");
    read_to_end(socket, Vec::new())
});

它不在教程中使用。为什么?@simbiont666,因为客户端示例中的HTTP服务器在发送页面时会关闭套接字(而服务器没有使用HTTP 1.1 keepalives)。非常感谢!