http - 如何使用超体通道?
问题描述
我正在尝试使用 Hyper 库发出 POST HTTP 请求,然后将数据写入其中,直到我关闭它(从多个函数/线程)。我在文档中找到了可以Body::channel()
用来执行此操作的文档,但我使用不当,因为我只能写入通道一次。我还没有找到任何例子,有人可以指出我正确的方向吗?
let (mut sender, body) = Body::channel();
let request = Request::builder()
.method(Method::POST)
.uri("http://localhost:3000/")
.header("content-type", "text")
.body(body)
.unwrap();
let client = Client::new();
let response = client.request(request);
//Does get sent
println!("Body: {:?}", sender.send_data(hyper::body::Bytes::from("test\n")).await);
//Stuck on this one
println!("Body: {:?}", sender.send_data(hyper::body::Bytes::from("test2\n")).await);
//Debug print
println!("{:?}", response.await);
解决方案
您需要将send_data()
行包装在tokio::spawn(async move { ... });
.
问题是Body
/Sender
只有缓冲区大小为 1。所以第二次send_data()
调用导致它await
(内部)直到Sender
准备好。这就是随后导致它“卡住”的原因。
这可以通过使用解决,tokio::spawn()
因为它最终允许await
ing ResponseFuture
,这会导致请求被执行。
let (sender, body) = Body::channel();
let request = Request::builder()
.method(Method::POST)
.uri("http://localhost:3000/")
.header("content-type", "text")
.body(body)
.unwrap();
let client = Client::new();
let response = client.request(request);
tokio::spawn(async move {
let mut sender = sender;
println!("Body: {:?}", sender.send_data(hyper::body::Bytes::from("test\n")).await);
println!("Body: {:?}", sender.send_data(hyper::body::Bytes::from("test2\n")).await);
});
println!("{:?}", response.await);
文档中没有提到缓冲区大小(据我所知)。但是,您可以通过检查与相关的源Body::channel()
来弄清楚这一点,您可以在其中看到它使用futures_channel::mpsc::channel(0)
. 文档提到缓冲区大小是buffer + num-senders
,在我们的例子中是0 + 1
。
推荐阅读
- c# - 无法从 Azure 应用代理 url 执行注销
- javascript - 将点数组作为形状围绕其中心垂直或水平翻转
- html - 无法让占位符出现在输入框中
- sql - SQL oracle where date field = Last Friday
- django - Django 3.1.1 NOT NULL 约束因日期而失败
- caching - 我可以将相同的 Redis 实例用于任务队列和缓存吗?
- macos - NSTextView 标准查找面板:在搜索中管理智能引号
- vb.net - 使用 Oxyplot 创建热图和 ContourSeries
- html - CSS 动画 - filter:blur() 不能与 transform:scale() 一起使用
- least-squares - 当使用仅具有 1 个未知参数的 optimize.least_square 时,与残差数组的形状相关的问题