gpt4 book ai didi

rust - "tokio::mpsc::channel"上的接收器仅在缓冲区已满时接收消息

转载 作者:行者123 更新时间:2023-12-03 11:29:37 24 4
gpt4 key购买 nike

在我的代码片段中,tokio (v0.3) mpsc:channel接收器仅在缓冲区已满时接收消息。缓冲区的大小无关紧要。

use std::io;
use std::net::{SocketAddr, ToSocketAddrs};
use std::sync::Arc;
use std::time::Duration;
use tokio::net::UdpSocket;
use tokio::sync::mpsc;
use tokio::time::sleep;

const MESSAGE_LENGTH: usize = 1024;

pub struct Peer {
socket: Arc<UdpSocket>,
}

impl Peer {
pub fn new<S: ToSocketAddrs>(addr: S) -> Peer {
let socket = std::net::UdpSocket::bind(addr).expect("could not create socket");

let peer = Peer {
socket: Arc::new(UdpSocket::from_std(socket).unwrap()),
};

peer.start_inbound_message_handler();
peer
}

pub fn local_addr(&self) -> SocketAddr {
self.socket.local_addr().unwrap()
}

fn start_inbound_message_handler(&self) {
let socket = self.socket.clone();
let (tx, rx) = mpsc::channel(1);

self.start_request_handler(rx);

tokio::spawn(async move {
let mut buf = [0u8; MESSAGE_LENGTH];
loop {
if let Ok((len, addr)) = socket.recv_from(&mut buf).await {
println!("received {} bytes from {}", len, addr);

if let Err(_) = tx.send(true).await {
println!("error sending msg to request handler");
}
}
}
});
}

fn start_request_handler(&self, mut receiver: mpsc::Receiver<bool>) {
tokio::spawn(async move {
while let Some(msg) = receiver.recv().await {
println!("got ping request: {:?}", msg);
}
});
}

pub async fn send_ping(&self, dest: String) -> Result<(), io::Error> {
let buf = [255u8; MESSAGE_LENGTH];

self.socket.send_to(&buf[..], &dest).await?;

Ok(())
}
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let peer1 = Peer::new("0.0.0.0:0");
println!("peer1 started on: {}", peer1.local_addr().to_string());

let peer2 = Peer::new("0.0.0.0:0");
println!("peer2 started on: {}", peer2.local_addr().to_string());

peer2.send_ping(peer1.local_addr().to_string()).await?;
peer2.send_ping(peer1.local_addr().to_string()).await?;

sleep(Duration::from_secs(100)).await;

Ok(())
}
链接到 Playground
start_inbound_message_handler函数我从套接字开始读取,如果收到消息,则消息通过 mpsc::channel将发送至 start_request_handler在处理发生的地方,在这种情况下,如果接收方接收到任何内容,将写入一个简单的日志输出。
main函数 我正在创建两个对等点,peer1 和 peer2,在创建两个对等点之后,我开始向第一个对等点发出 ping 请求。在 start_inbound_message_handler我将从 udp 套接字接收数据并通过 mpsc::channel 发送消息发送返回没有错误。问题如前所述,接收方只会在缓冲区已满时接收消息。在这种情况下,缓冲区是 1 .因此,如果我发送第二个 ping,则会收到第一个 ping。我不知道为什么会发生这种情况。
预期的行为是,如果我通过 channel 发送消息,接收方会立即开始接收消息,并且不会等到缓冲区已满。

最佳答案

根据 from_std() 的 Tokio 文档:

Creates new UdpSocket from a previously bound std::net::UdpSocket.

This function is intended to be used to wrap a UDP socket from thestandard library in the Tokio equivalent. The conversion assumes nothingabout the underlying socket; it is left up to the user to set it innon-blocking mode.

This can be used in conjunction with socket2's Socket interface toconfigure a socket before it's handed off, such as setting options likereuse_address or binding to multiple addresses.


未处于非阻塞模式的套接字将阻止 Tokio 正常工作。
只需使用 tokio 功能 bind() ,就简单多了。

关于rust - "tokio::mpsc::channel"上的接收器仅在缓冲区已满时接收消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64649405/

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