Rust Tokio future从一个通道读取数据,并使用poll\u fn和try\u ready,这永远不会完成

Rust Tokio future从一个通道读取数据,并使用poll\u fn和try\u ready,这永远不会完成,rust,future,rust-tokio,Rust,Future,Rust Tokio,我有一个永远不会完成的东京未来(rx是一个Receiver,sock是一个东京UdpSocket)。它基本上从数据包队列中读取数据包,并通过套接字进行传输: poll_fn(move || { match try_ready!(rx .poll() .map_err(|_e| tokio::io::Error::new(tokio::io::ErrorKind::Other, "Poll error"))) { Some((pack

我有一个永远不会完成的东京未来(
rx
是一个
Receiver
sock
是一个东京
UdpSocket
)。它基本上从数据包队列中读取数据包,并通过套接字进行传输:

poll_fn(move || {
    match try_ready!(rx
        .poll()
        .map_err(|_e| tokio::io::Error::new(tokio::io::ErrorKind::Other, "Poll error")))
    {
        Some((packet, to)) => {
            println!(
                "Rx: Received {} bytes for {}: {:?}",
                packet.len(),
                to,
                packet.as_slice(),
            );
            try_ready!(sock.poll_send_to(packet.as_slice(), &to));
            println!("Sent");
        }
        None => println!("Rx end"),
    }
    Ok(futures::Async::Ready(()))
})
.map_err(|e: tokio::io::Error| println!("Error: {:?}", e))
它一直执行到
poll\u send\u to
行(执行
poll\u send\u to
之前的
println!
之后的
println!
不会执行),然后一直等待,不发送数据包

我将上述未来替换为以下未来,以确保它不是套接字问题(我认为以前的通知存在一些问题):

这个未来工作得很好——它按预期发送数据包并退出程序

鉴于
rx
可以
poll
成功并打印
println
消息,我认为问题不在于消息通道。我不认为问题出在插座上,因为第二个未来是可行的。我通过Wireshark直接观察数据包,所以我认为这也不是我观察的问题

我对Rust和Tokio还很陌生,所以我可能忽略了一些基本事实(例如,在同一个未来不能
尝试两次,未来不会从之前中断的地方恢复,等等)

你能帮我解决第一个未来的问题吗

use futures::future::lazy;
use futures::stream::Stream;
use futures::try_ready;
use std::net::SocketAddr;
use std::str::FromStr;
use tokio;
use tokio::net::UdpSocket;
use tokio::prelude::future::poll_fn;
use tokio::prelude::Future;

fn main() {
    let mut sock = UdpSocket::bind(&SocketAddr::from_str("127.0.0.1:8000").expect("Parse error"))
        .expect("Bind error");

    let (mut tx, mut rx) = tokio::sync::mpsc::channel::<(Vec<u8>, SocketAddr)>(2000);

    tokio::run(lazy(move || {
        //----------------- This future works ----------------//
        // tokio::spawn(
        //     poll_fn(move || {
        //         let packet = vec![70; 10];
        //         let to = SocketAddr::from_str("127.0.0.1:8001").expect("Parse error");
        //         try_ready!(sock.poll_send_to(packet.as_slice(), &to));
        //         Ok(futures::Async::Ready(()))
        //     })
        //     .map_err(|e: tokio::io::Error| println!("Error: {:?}", e)),
        // );

        //----------------- This future doesn't ----------------//
        tokio::spawn(
            poll_fn(move || {
                match try_ready!(rx
                    .poll()
                    .map_err(|_e| tokio::io::Error::new(tokio::io::ErrorKind::Other, "Poll error")))
                {
                    Some((packet, to)) => {
                        // This is printed
                        println!(
                            "Rx: Received {} bytes for {}: {:?}",
                            packet.len(),
                            to,
                            packet.as_slice(),
                        );
                        try_ready!(sock.poll_send_to(packet.as_slice(), &to));
                        // This is never printed
                        println!("Sent");
                    }
                    None => println!("Rx end"),
                }
                Ok(futures::Async::Ready(()))
            })
            .map_err(|e: tokio::io::Error| println!("Error: {:?}", e)),
        );

        //----------------- This future queues a packet ----------------//
        tokio::spawn(
            poll_fn(move || {
                try_ready!(tx.poll_ready());
                tx.try_send((
                    vec![70; 10],
                    SocketAddr::from_str("127.0.0.1:8001").expect("Parse error"),
                ))
                .expect("Send error");
                // Wait permanently so message channel doesn't get disconnected
                // Achieved differently in production
                Ok(futures::Async::NotReady)
            })
            .map_err(|e: tokio::sync::mpsc::error::SendError| println!("Error: {:?}", e)),
        );

        Ok(())
    }));
}
use futures::future::lazy;
使用futures::stream::stream;
使用futures::try_ready;
使用std::net::SocketAddr;
使用std::str::FromStr;
使用东京;
使用tokio::net::UdpSocket;
使用东京::前奏::未来::投票;
使用东京:前奏:未来;
fn main(){
让mut sock=UdpSocket::bind(&SocketAddr::from_str(“127.0.0.1:8000”)。预期(“解析错误”)
.expect(“绑定错误”);
let(mut-tx,mut-rx)=东京::同步::mpsc::信道::(2000);
东京:跑(懒)(移动){
//-----------------这个未来是可行的----------------//
//东京:繁殖(
//投票站(移动){
//让packet=vec![70;10];
//let to=SocketAddr::from_str(“127.0.0.1:8001”)。expect(“解析错误”);
//试试准备!(sock.poll\u send\u to(packet.as\u slice(),&to));
//好(未来::异步::就绪(())
//     })
//.map_err(| e:tokio::io::Error | println!(“Error:{:?}”,e)),
// );
//-----------------这个未来不会----------------//
东京:繁殖(
投票站(移动){
比赛准备就绪!(rx)
.poll()
.map_err(|e|tokio::io::Error::new(tokio::io::ErrorKind::Other,“轮询错误”))
{
一些((数据包,到))=>{
//这是印刷品
普林顿(
“Rx:接收到{}:{:?}的{}字节”,
packet.len(),
到
packet.as_slice(),
);
试试准备!(sock.poll\u send\u to(packet.as\u slice(),&to));
//这是从未印刷过的
println!(“已发送”);
}
无=>println!(“接收端”),
}
好(未来::异步::就绪(())
})
.map_err(| e:tokio::io::Error | println!(“Error:{:?}”,e)),
);
//-----------------这是一个数据包的队列----------------//
东京:繁殖(
投票站(移动){
试试看准备好了吗!(tx.poll_ready());
tx.try\u发送((
vec![70;10],
SocketAddr::from_str(“127.0.0.1:8001”).expect(“解析错误”),
))
.expect(“发送错误”);
//永久等待,以便消息通道不会断开连接
//在生产中取得不同的成就
正常(未来::异步::未就绪)
})
.map_err(| e:tokio::sync::mpsc::error::senderro | println!(“error:{:?}”,e)),
);
好(())
}));
}

使用此版本的future会显示问题:

tokio::spawn(
    future::poll_fn(move || {
        eprintln!("Starting poll_fn");

        let from_channel = rx
            .poll()
            .map_err(|_e| tokio::io::Error::new(tokio::io::ErrorKind::Other, "Poll error"));

        if let Some((packet, to)) = futures::try_ready!(dbg!(from_channel)) {
            futures::try_ready!(dbg!(sock.poll_send_to(packet.as_slice(), &to)));
        }
        Ok(futures::Async::Ready(()))
    })
    .map_err(|e: tokio::io::Error| println!("Error: {:?}", e)),
);
以下是稍微清理过的输出:

开始轮询\u fn
[src/main.rs:21]来自_通道=正常(未就绪)
开始投票(fn)
[src/main.rs:21]from_channel=Ok(就绪(一些(/*…*/))
[src/main.rs:22]sock.poll\u send\u to(packet.as\u slice(),&to)=Ok(NotReady)
开始投票(fn)
[src/main.rs:21]来自_通道=正常(未就绪)
简言之:

  • 未来开始了
  • 频道没有准备好任何东西;频道注册一个通知
  • 未来回归
  • 通道获取一个值并通知任务
  • 未来再次开始
  • 通道中有一个值已准备就绪
  • 套接字上的发送尚未准备就绪;套接字注册一个通知
  • 未来回归
  • 套接字被清除并通知任务
  • 未来再次开始
  • 频道没有准备好任何节目;频道注册一个通知
  • 未来回归
  • 频道中不会添加任何其他内容
  • 简而言之,您没有在未来正确维护您的状态机。你需要知道你上一次运行future时走了多远,并在下一次运行时从这一点开始

    async
    /
    await
    语法之所以备受期待,是因为它将为您编写这些状态机

    我不知道您为什么选择使用较低级别的
    poll
    界面。我会使用更高级别的
    未来的

    tokio::spawn({
        rx.fold(sock, |sock, (packet, to)| {
            sock.send_dgram(packet, &to)
                .inspect(|_| println!("Sent it!"))
                .map(|(sock, _)| sock)
                .map_err(|e| panic!("Error: {:?}", e))
        })
        .map(drop)
        .map_err(|e| panic!("Error: {:?}", e))
    });
    

    基于
    的未来接口[…]在出错时销毁套接字(和缓冲区)

    这是使用基于
    poll
    的界面的一个很好的理由,但我还是会花足够长的时间来实现您自己的未来
    tokio::spawn({
        rx.fold(sock, |sock, (packet, to)| {
            sock.send_dgram(packet, &to)
                .inspect(|_| println!("Sent it!"))
                .map(|(sock, _)| sock)
                .map_err(|e| panic!("Error: {:?}", e))
        })
        .map(drop)
        .map_err(|e| panic!("Error: {:?}", e))
    });
    
    struct X(UdpSocket);
    struct XSendGram<D> {
        sock: Option<UdpSocket>,
        data: D,
        addr: SocketAddr,
    }
    
    impl X {
        fn send_dgram<D>(self, data: D, addr: SocketAddr) -> XSendGram<D> {
            XSendGram {
                sock: Some(self.0),
                data,
                addr,
            }
        }
    }
    
    impl<D> Future for XSendGram<D>
    where
        D: AsRef<[u8]>,
    {
        type Item = (X, usize);
        type Error = (X, std::io::Error);
    
        fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {
            let mut sock = self.sock.take().expect("Future called after success or failure");
    
            match sock.poll_send_to(self.data.as_ref(), &self.addr) {
                Ok(Async::Ready(bytes)) => Ok(Async::Ready((X(sock), bytes))),
                Ok(Async::NotReady) => {
                    self.sock = Some(sock); // Restore it for the next call
                    Ok(Async::NotReady)
                }
                Err(e) => Err((X(sock), e)),
            }
        }
    }
    
    tokio::spawn({
        rx.fold(X(sock), |sock, (packet, to)| {
            sock.send_dgram(packet, to)
                .inspect(|(_, n)| println!("Sent {} bytes", n))
                .then(|r| match r {
                    Ok((sock, _)) | Err((sock, _)) => future::ok(sock),
                })
        })
        .map(drop)
        .map_err(|e| panic!("Error: {:?}", e))
    });