Rust 当多个期货使用相同的基础套接字时,为什么我不能得到唤醒?

Rust 当多个期货使用相同的基础套接字时,为什么我不能得到唤醒?,rust,future,rust-tokio,Rust,Future,Rust Tokio,我有一段代码,它使用相同的本地UdpSocket将数据发送到多个UDP端点: use futures::stream::FuturesUnordered; 使用futures::StreamText; 使用std::{ 未来, net::{Ipv4Addr,SocketAddr}, pin::pin, 任务::{Context,Poll}, }; 使用tokio::net::UdpSocket; #[tokio::main] 异步fn main(){ 让服务器_0:SocketAddr=(Ipv

我有一段代码,它使用相同的本地UdpSocket将数据发送到多个UDP端点:

use futures::stream::FuturesUnordered;
使用futures::StreamText;
使用std::{
未来,
net::{Ipv4Addr,SocketAddr},
pin::pin,
任务::{Context,Poll},
};
使用tokio::net::UdpSocket;
#[tokio::main]
异步fn main(){
让服务器_0:SocketAddr=(Ipv4Addr::UNSPECIFIED,12000).into();
让服务器_2:SocketAddr=(Ipv4Addr::UNSPECIFIED,12002).into();
让服务器_1:SocketAddr=(Ipv4Addr::UNSPECIFIED,12001).into();
tokio::spawn(启动服务器(服务器0));
tokio::spawn(启动_服务器(服务器_1));
tokio::spawn(启动_服务器(服务器_2));
让client_addr:SocketAddr=(Ipv4Addr::UNSPECIFIED,12004).into();
让socket=UdpSocket::bind(client_addr).wait.unwrap();
让mut futs=FuturesUnordered::new();
futs.push(任务::new(0,&socket,&server_0));
futs.push(任务::new(1,&socket,&server_1));
futs.push(任务::new(2,&socket,&server_2));
而让一些(n)=futs.next()等待{
println!(“完成:{:?}”,n)
}
}
异步fn启动\u服务器(地址:SocketAddr){
让mut socket=UdpSocket::bind(addr).wait.unwrap();
设mut buf=[0;512];
环路{
println!(“{:?}”,socket.recv_from(&mutbuf.wait);
}
}
结构任务{
类型输出=选项;

fn民意测验(self:Pin,cx:&mut Context当
poll\u send\u to
返回
poll::Pending
时,它保证对轮询上下文中提供的
唤醒器发出唤醒。但是,它只需要对轮询它的最后一个
唤醒器发出唤醒。这意味着,因为您正在调用
poll\nd_to
在来自多个任务的同一套接字上,该套接字只承诺向最后轮询它的套接字发出唤醒

这也解释了为什么这样做有效:

let mut futs = Vec::new();
futs.push(Task::new(0, &socket, &server_0));
futs.push(Task::new(1, &socket, &server_1));
futs.push(Task::new(2, &socket, &server_2));

for n in join_all(futs).await {
    println!("Done: {:?}", n)
}
FuturesUnordered
不同,
join\u all
组合器将在每次轮询时轮询每个内部未来,但
FuturesUnordered
会跟踪唤醒来自哪个潜在未来


另请参见。

结果证明您是对的,有时我的解决方案也不起作用,那么您是否尝试过
cx.waker().wake\u by\u ref()
在接收时调用此选项
Poll::Pending
,因为
Waker
只会唤醒当前任务,而不会唤醒其他任务。如果您的未来等待时间较长,这是一种解决方法,这会带来较高的cpu使用率。作为一个简单的解决方案,您可以在单独的线程上调用这些唤醒器,并超时(我的意思是轮询).:…&可用于唤醒当前任务的Waker。但这不是提供相同的行为,对吗?它将等待所有的未来完成以产生结果?是的,添加它只是为了帮助解释出错的原因。有关替代方案的讨论可以在链接的线程中进行。当然,我阅读了所有内容,谢谢,但我有一个问题,谁唤醒tokio executor首次轮询后的
JoinAll
任务?确实内部任务不会这样做,因为我们有这个问题?仍然会有三个任务中的一个会收到通知。问题是
JoinAll
会在其中任何一个任务收到通知时轮询内部的所有任务,这与
FuturesUnordered 只通知其中一个任务并不重要;它们仍然会被轮询。那么这意味着,如果所有的期货在第一次轮询时返回pending,那么它将不起作用?如本例所示?