如何检测套接字未侦听 udp

How to detect that socket is not listening for udp

提问人:MarieGosnell 提问时间:11/6/2023 最后编辑:MarieGosnell 更新时间:11/7/2023 访问量:36

问:

我正在尝试通过udp发送数据。它有效,但是即使目标套接字不存在,我也不会收到任何错误。有没有办法检测套接字没有在听?

我正在使用这段代码。端口 8081 上没有任何内容在侦听,但我根本没有收到错误。相反,如果我从 python 执行相同的操作,我会收到错误消息“连接被拒绝”。

use tokio::net::UdpSocket;
use std::error::Error;
use std::io;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let socket = UdpSocket::bind("127.0.0.1:8080").await?;

    let dst = "127.0.0.1:8081".parse()?;

    loop {
        socket.writable().await?;

        match socket.try_send_to(&b"hello world"[..], dst) {
            Ok(sent) => {
                println!("sent {} bytes", sent);
            }
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                // Writable false positive.
                println!("{e}");
            }
            Err(e) => return Err(e.into()),
        }
    }

    Ok(())
}

更新:根据下面的 Steffen 评论更新了代码。在向非侦听端口发送 udp 消息时仍然没有错误。

锈-tokio

评论

0赞 Steffen Ullrich 11/6/2023
如果我从 python 做同样的事情,我会收到错误消息“连接被拒绝” - 我对此表示怀疑。如果您在 Python 中对没有人绑定的 UDP 目标执行单个操作,则不会出现错误。您最多应该在第二个时收到错误,因为这样就无法访问ICMP将被处理并标记为套接字上的问题。如果您不这么认为,请显示您使用的实际 Python 代码。sendsend
0赞 MarieGosnell 11/7/2023
使用上面的代码,我尝试发送 100 多条消息,但从未在send_to上出现任何错误?!
0赞 Steffen Ullrich 11/7/2023
同样,请提供匹配的 python 代码。如果我像您一样构建代码,我不会在 python 中遇到任何错误 - 使用 sendto 和未连接的套接字。我只收到使用 send 连接套接字的错误。
0赞 MarieGosnell 11/7/2023
啊,我明白你的意思了......在 python 中,我确实绑定到套接字,然后绑定到 sendall。这就是它起作用的原因!所以,就我而言,对于 Rust,我需要做同样的事情。我说得对吗?

答:

1赞 Steffen Ullrich 11/7/2023 #1

UDP 没有像 TCP 那样的真正连接,即在发送任何数据之前建立初始连接。因此,为了检测目的地是否有某些UDP侦听器,需要在那里发送数据包,然后检查是否收到数据包。

UDP 有一种机制:如果接收系统在没有侦听器的情况下获得 IP 端口的 UDP 数据包,它将发送回无法访问的 ICMP(对于 IPv4,IPv6 的类似消息)。假设此 ICMP 数据包实际上到达了原始发送方(即没有防火墙阻止它),那么套接字将被标记为此错误,并且该错误将在下一个套接字操作中传递,就像另一个发送一样。

但是,这只有在连接插座时才成立,即 在您的示例中调用(并使用代替 )。对于未连接的套接字(如您的情况),不会传递错误,因为它与特定连接不匹配(因为没有连接)。socket.connect("127.0.0.1:8081")socket.try_sendsocket.try_send_to

如果我从 python 执行相同的操作,我会收到错误消息“连接被拒绝”

如果您在 Python 中使用未连接的套接字,您也不会收到错误。如果使用连接的套接字,则会出现错误。因此,您的 python 代码可能没有像 rust 代码那样“相同”。

(来自评论)在 python 中,我确实绑定到套接字,然后绑定到 sendall。

sendall没有目标参数,因此它需要连接的套接字。因此,错误被传递到连接的套接字。