发送并行请求并返回rust中的前200个响应

x33g5p2x  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(157)

我尝试在Rust中编写一个发现函数,发现LAN中的设备IP,此函数应发送IP空间中所有可能IP的HTTP请求,一旦接收到200状态,则返回值并取消所有其他请求(通过丢弃将来使用的reqwest)

async fn discover() -> Result<String, ()> {
    for i in 0..256 {
        tokio::spawn(async move {
            let url = format!("http://192.168.0.{i}:8000/ping");

            reqwest::get(url).await;
        });
    }
}

编辑1

一旦接收到200状态,则返回该值并取消所有其他请求
我们还想验证响应内容,以确保这是正确的设备,而不是试图监视网络的人。我们将通过验证从/ping端点返回的JWT标记来验证响应,我们如何才能做到这一点

4zcjmb1e

4zcjmb1e1#

这可以通过futures-crate和select_ok()来实现。
您可以执行以下操作:

  • 转换Iterator中的范围,并将每个元素iMap到 reqwest 请求中。select_ok需要Vec中的Futures来实现UnPin;这就是我在这里使用.boxed()的原因。
  • 将期货的Vec传递到select_ok
  • response将包含第一个成功的未来结果
  • 我们可以使用remaining_futures来取消drop的剩余请求(我不确定这是否有效,您需要对此进行测试)
use futures::{future::select_ok, FutureExt};

async fn discover() {
    let futures = (0..256)
        .into_iter()
        .map(|i| {
            let url = format!("http://192.168.0.{i}:8000/ping");

            return reqwest::get(url).boxed();
        })
        .collect::<Vec<_>>();

    let (response, mut remaining_futures) = select_ok(futures).await.unwrap();

    remaining_futures.iter_mut().for_each(|f| drop(f));
}

相关问题