我之前问过 Asynchronously reconnecting a client to a server in an infinite loop,my final solution。这是我问题的第一部分,我不能理清第二部分。
我有一个无界限的频道,我需要将此频道收到的数据流式传输到远程服务器。如果与远程服务器的连接丢失,那么我将重新启动它并重试来自同一频道的流数据。
我想到的解决方案是将UnboundedReceiver
传递给尝试连接到服务器的方法,转发此方法中的数据并返回连接丢失时收到的UnboundedReceiver
,所以无限循环可以重新获取UnboundedReceiver
的所有权,并再次将其传递给循环方法。
如何从我的UnboundedReceiver
方法返回此send_data_to_remote_server()
?
以下是代码示例:
extern crate futures;
extern crate tokio_core;
extern crate tokio_line;
use futures::future::{self, Future, Loop};
use futures::{Stream, Sink};
use futures::sync::mpsc::{self, UnboundedSender, UnboundedReceiver};
use tokio_core::io::{Io};
use tokio_core::net::{TcpStream};
use tokio_core::reactor::{Core, Handle};
use tokio_line::LineCodec;
use std::{io, str};
use std::{thread, time};
fn send_data_to_remote_server(handle: &Handle, bufrx: UnboundedReceiver<String>) -> Box<Future<Item = UnboundedReceiver<String>, Error = io::Error>> {
let remote_addr = "127.0.0.1:9876".parse().unwrap();
let tcp = TcpStream::connect(&remote_addr, handle);
let client = tcp.and_then(move |stream| {
let (sender, receiver) = stream.framed(LineCodec).split();
let reader = receiver
.for_each(|message| {
println!("{}", message);
Ok(())
})
.and_then(|bufrx| {
println!("CLIENT DISCONNECTED");
/***************** START FIXME ************/
let (_, bufrx) = mpsc::unbounded(); //FIXME: `bufrx` received in a clousure is actually an `()` so I can't use it, I put this here only as sample and to satisfy the compiler
/***************** END FIXME ************/
Ok(bufrx)
});
let writer = bufrx
.map_err(|_| io::Error::new(io::ErrorKind::Other, "error kind returned should be the same of `sender` sink in `forward()`"))
.forward(sender)
.and_then(|(bufrx, sender)| {
// bufrx
/***************** START FIXME ************/
let (_, bufrx) = mpsc::unbounded(); //FIXME: `bufrx` received in a clousure is actually an `()` so I can't use it, I put this here only as sample and to satisfy the compiler
/***************** END FIXME ************/
Ok(bufrx)
});
reader.select(writer)
.map(|(bufrx, nf)| {
bufrx
})
.map_err(|(err, nf)| {
err
})
}).or_else(|_| {
println!("connection refuse");
Err(io::Error::new(io::ErrorKind::Other, "connection refuse"))
});
Box::new(client)
}
fn main() {
let mut core = Core::new().unwrap();
let handle = core.handle();
let (buftx, bufrx) = mpsc::unbounded();
let client = future::loop_fn(bufrx, |bufrx| {
send_data_to_remote_server(&handle, bufrx)
.map(|bufrx| -> Loop<UnboundedReceiver<String>, UnboundedReceiver<String>> {
/***************** START FIXME ************/
// actually the `bufrx` received in this clouser is not the original one, but I
// think that the fix should be made in the `send_data_to_remote_server()` method
/***************** END FIXME ************/
Loop::Continue(bufrx)
})
.or_else(|err| -> Result<Loop<UnboundedReceiver<String>, UnboundedReceiver<String>>, ()> {
thread::sleep(time::Duration::from_millis(50));
/***************** START FIXME ************/
let (_, bufrx) = mpsc::unbounded(); //FIXME: argument received in a clousure is actually an `io::Error` and I lost the ownership of the original bufrx so I can't use it, I put this here only as sa↪mple and to satisfy the compiler
/***************** END FIXME ************/
Ok(Loop::Continue(bufrx))
})
});
core.run(client).unwrap();
}
添加tokio-line crate:
tokio-line = { git = "https://github.com/tokio-rs/tokio-line" }