我正在尝试通过udp发送数据。它可以工作,但是即使目标套接字不存在,我也没有收到任何错误。有什么方法可以检测到套接字没有监听吗?
我正在使用这段代码。没有任何东西在端口8081上侦听,但我根本没有收到错误。相反,如果我从python上做同样的事情,我会收到错误消息“Connection refused”。
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消息到非侦听端口。
1条答案
按热度按时间3htmauhk1#
UDP没有TCP那样的真实的连接,即在发送任何数据之前建立初始连接。因此,为了检测目的地是否有UDP侦听器,需要发送一个数据包,然后检查数据包是否被接收。
UDP对此有一种机制:如果接收系统收到一个没有监听器的IP端口的UDP数据包,它将发送一个无法到达的HTTP消息(对于IPv4,类似于IPv6的消息)。假设这个HTTP数据包实际上到达了原始发送者(即没有防火墙阻止它),那么套接字将被标记为这个错误,并且错误将在下一个套接字操作中传递,就像另一个发送一样。
但是,这仅在套接字连接时才成立,即在您的示例中调用
socket.connect("127.0.0.1:8081")
(并且使用socket.try_send
代替socket.try_send_to
)。对于未连接的套接字(如您的情况),错误不会被传递,因为它不匹配特定的连接(因为没有连接)。如果我从python做同样的事情,我会得到错误消息“连接拒绝”
如果你在Python中使用一个未连接的套接字,你也不会得到错误。如果你使用一个连接的套接字,你会得到错误。所以很可能你的Python代码没有做你的Rust代码所做的“相同”。
(from注解)在python中,我确实绑定到了socket,然后sendall。
sendall
没有目的地参数,所以它需要一个连接的套接字。因此错误被传递到连接的套接字。