提问人:MarieGosnell 提问时间:11/6/2023 最后编辑:MarieGosnell 更新时间:11/7/2023 访问量:36
如何检测套接字未侦听 udp
How to detect that socket is not listening for udp
问:
我正在尝试通过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 消息时仍然没有错误。
答:
UDP 没有像 TCP 那样的真正连接,即在发送任何数据之前建立初始连接。因此,为了检测目的地是否有某些UDP侦听器,需要在那里发送数据包,然后检查是否收到数据包。
UDP 有一种机制:如果接收系统在没有侦听器的情况下获得 IP 端口的 UDP 数据包,它将发送回无法访问的 ICMP(对于 IPv4,IPv6 的类似消息)。假设此 ICMP 数据包实际上到达了原始发送方(即没有防火墙阻止它),那么套接字将被标记为此错误,并且该错误将在下一个套接字操作中传递,就像另一个发送一样。
但是,这只有在连接插座时才成立,即 在您的示例中调用(并使用代替 )。对于未连接的套接字(如您的情况),不会传递错误,因为它与特定连接不匹配(因为没有连接)。socket.connect("127.0.0.1:8081")
socket.try_send
socket.try_send_to
如果我从 python 执行相同的操作,我会收到错误消息“连接被拒绝”
如果您在 Python 中使用未连接的套接字,您也不会收到错误。如果使用连接的套接字,则会出现错误。因此,您的 python 代码可能没有像 rust 代码那样“相同”。
(来自评论)在 python 中,我确实绑定到套接字,然后绑定到 sendall。
sendall
没有目标参数,因此它需要连接的套接字。因此,错误被传递到连接的套接字。
评论
send
send