gpt4 book ai didi

rust - Hyper 服务器在未来返回 Async::NotReady 时断开连接

转载 作者:行者123 更新时间:2023-11-29 08:08:29 32 4
gpt4 key购买 nike

我正在尝试运行一个 super 服务器,它使用 future 对请求进行异步响应。当 future 的 poll 方法被调用并返回 Async::NotReady 时,连接就被丢弃了(“dropping I/O source: 0”)。我预计 poll 方法会被多次调用,直到它返回 Async::Ready

example shown返回一个异步 io future ,它正在做(我猜)同样的事情。

为什么 future 的 poll 函数只被调用一次,为什么 hyper 在 future 返回 Async::NotReady 后断开连接?

示例代码:( super 版本为:v0.12.21)

use futures::{Async, Future, Poll};
use hyper::http::{Request, Response};
use hyper::service::service_fn;
use hyper::{Body, Server};

fn main() {
let addr = ([127, 0, 0, 1], 3335).into();
println!("Start request handler. (Listening on http://{})", addr);

hyper::rt::run(
Server::bind(&addr)
.serve(|| service_fn(|request: Request<Body>| handle_request(request.uri().path())))
.map_err(|e| println!("server error: {}", e)),
);
}

type BoxedResponseFuture = Box<Future<Item = Response<Body>, Error = tokio::io::Error> + Send>;

fn handle_request(path: &str) -> BoxedResponseFuture {
println!("Handle request {:?}", path);
Box::new(
ResponseFuture { ready: false }
.and_then(|_| {
let response = Response::new(Body::from("Success".to_string()));

Ok(response)
})
.or_else(|e| {
let response = Response::new(Body::from(format!("Error: {:?}", e)));

Ok(response)
}),
)
}

struct ResponseFuture {
ready: bool,
}

impl Future for ResponseFuture {
type Item = ();
type Error = ();

fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
println!("Poll future");

if self.ready {
println!("Future ready");

return Ok(Async::Ready(()));
}

println!("Future not ready");
self.ready = true;
Ok(Async::NotReady)
}
}

最佳答案

Hyper 建立在 futures crate 之上,并使用称为“就绪”或“拉动”的 future 模型,其中值按需从 futures 中拉出,否则通知任务什么时候可以提取值。

poll 返回NotReady 时,当前任务必须注册准备就绪更改通知,否则任务可能永远无法完成。任何返回 Async 的函数都必须遵守它。

换句话说,你应该等到poll可以返回Ready或者通知当前任务表明它已经准备好进行并返回NotReady

// notify about progress
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
println!("Poll future");

if self.ready {
println!("Future ready");

return Ok(Async::Ready(()));
}

println!("Future not ready");
self.ready = true;

// The executor will poll this task next iteration
futures::task::current().notify();
Ok(Async::NotReady)
}

// wait until it is Ready
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
loop {
println!("Poll future");

if self.ready {
println!("Future ready");
return Ok(Async::Ready(()));
}

println!("Future not ready");
self.ready = true;
}
}

Tokio 的文档 1 2可能会澄清。

关于rust - Hyper 服务器在未来返回 Async::NotReady 时断开连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54252530/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com