在无限循环中将内容流式传输到远程服务器

时间:2017-03-11 14:52:25

标签: rust rust-tokio

我之前问过 Asynchronously reconnecting a client to a server in an infinite loopmy 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" }

0 个答案:

没有答案