很抱歉,Rust和Tokio的新手都提出了一个愚蠢的新手问题,但是如果有人能让我知道这是什么/为什么让我感到痛苦,我将不胜感激。我可能可以使用其他方法对此问题进行编码,但我想知道为什么这似乎行不通。
我正在尝试在Tokio中处理一些代码,这些代码创建一个TCP侦听器,然后自动将接收到的JSON转换为Rust结构。似乎使用编解码器可能是一个很好的解决方案,但到目前为止我尝试过的工作似乎无效。
下面是一个最小的程序,我在其中创建了这样的侦听器,只需使用提供的LinesCodec尝试使它解释与它建立的连接:
extern crate tokio;
use std::net::SocketAddr;
use tokio::codec::{LinesCodec, FramedRead};
use tokio::net::TcpListener;
use tokio::prelude::*;
fn main() {
let addr = "127.0.0.1:12345".parse::<SocketAddr>().unwrap();
let listener = TcpListener::bind(&addr).unwrap();
tokio::run(listener.incoming()
.map_err(|e| eprintln!("failed to accept socket; error = {:?}", e))
.for_each(move |socket| {
let transport = FramedRead::new(socket, LinesCodec::new());
transport.for_each(|msg| {
println!("Received: {:?}", msg);
Ok(())
});
Ok(())
})
);
}
这会编译,当我通过telnet或通过快速python脚本通过发送带换行符的字符串来发送一行时,我再也无法获得期望的打印消息。
编译器会给出有用的警告:
warning: unused `tokio::prelude::stream::ForEach` that must be used
--> src/main.rs:18:13
|
18 | / transport.for_each(|msg| {
19 | | println!("Received: {:?}", msg);
20 | | Ok(())
21 | | });
| |_______________^
|
= note: #[warn(unused_must_use)] on by default
= note: streams do nothing unless polled
所以我尝试如下更改transport.for_each
:
let mut stream = transport.for_each(|msg| {
println!("Received: {:?}", msg);
Ok(())
});
loop {
match stream.poll() {
Ok(s) => {
match s {
Async::Ready(t) => println!("Ready: {:?}", t),
Async::NotReady => println!("Not ready"),
}
}
<snip>
}
}
警告现在消失了,我在终端上收到几行说“未准备好”的行。我在做什么错了?
我也尝试使用调试功能来创建自己的基本LinesCodec,但据我所知,它永远不会被调用。然而,根据我在https://tokio.rs/docs/going-deeper/frames/末尾看到的内容,它应该会收到我的消息。
任何帮助将不胜感激,其中包括回答说是从tokio-0.1.18转到0.3.x,因为对您要实现的目标有更好的支持。
答案 0 :(得分:0)
感谢tokio社区对此提供的帮助。警告是正确的,并且是正确的提示,但是在此处执行轮询不是正确的事情,这将导致它无限期地轮询。相反,我们以item()和error io :: Error结束将来,我们可以使用map_err将其映射到item()和error()到Future中,然后我们可以在该Future上运行tokio :: spawn有效。