如何“连接”一个 UDP 套接字并让 OS 选择端口和地址
How do I `connect` an UDP socket and let the OS choose the port and address
我想向服务器发送一个 UDP 查询并接收它的响应。在 C 中是:call socket
then connect
then write
then read
。操作系统负责选择合适的本地 IP 地址和端口来使用。
我正尝试在 Rust 中做同样的事情。但是如果我自己不指定地址和端口,我找不到获得 UdpSocket
的方法。我能做的最接近的是:
fn main() {
use std::net::{Ipv4Addr, UdpSocket};
let socket = UdpSocket::bind((Ipv4Addr::UNSPECIFIED, 12345)).unwrap();
socket.connect("1.1.1.1:53").unwrap();
socket.send(b"\x12\x34\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\
\x07example\x03com\x00\
\x00\x01\x00\x01").unwrap();
let mut buffer = [0; 512];
let len = socket.recv(&mut buffer).unwrap();
for b in &buffer[0..len] {
print!("{:02x} ", b);
}
println!("");
}
这可行,但与 C 版本相比有两个缺点。
如果我指定一个已经在使用的本地端口,它可能会失败,
套接字监听所有个可用地址,而C版本只监听“合适的”地址。这对于 UDP 很重要,可以避免响应欺骗。
比如我查询127.0.0.1,那么C版会自动绑定到127.0.0.1地址。互联网将无法欺骗我的查询的答案。另外,如果我有两个网络接口,一个连接到互联网,一个连接到我的本地网络,IP 为 192.168.0.1,我可以查询本地网络上的解析器,如 172.16.17.18。 C 版本将绑定到地址 192.168.0.1,我将确保答案不是来自互联网。
我怎样才能最好地做到与 C 版本相同?
编辑:解释关于寻找“合适”地址的第二点。
这并不明显,但是如果您将套接字绑定到 (UNSPECIFIED, 0)
,那么当您连接到远程地址时,本地地址将设置为适当的接口地址。 (端口0
表示自动分配一个端口,就像C中的未绑定套接字一样。)您可以在连接成功后在套接字上调用local_addr()
来确认这一点。
对于 POSIX 的复杂性,我深表歉意。 :-)
我想向服务器发送一个 UDP 查询并接收它的响应。在 C 中是:call socket
then connect
then write
then read
。操作系统负责选择合适的本地 IP 地址和端口来使用。
我正尝试在 Rust 中做同样的事情。但是如果我自己不指定地址和端口,我找不到获得 UdpSocket
的方法。我能做的最接近的是:
fn main() {
use std::net::{Ipv4Addr, UdpSocket};
let socket = UdpSocket::bind((Ipv4Addr::UNSPECIFIED, 12345)).unwrap();
socket.connect("1.1.1.1:53").unwrap();
socket.send(b"\x12\x34\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\
\x07example\x03com\x00\
\x00\x01\x00\x01").unwrap();
let mut buffer = [0; 512];
let len = socket.recv(&mut buffer).unwrap();
for b in &buffer[0..len] {
print!("{:02x} ", b);
}
println!("");
}
这可行,但与 C 版本相比有两个缺点。
如果我指定一个已经在使用的本地端口,它可能会失败,
套接字监听所有个可用地址,而C版本只监听“合适的”地址。这对于 UDP 很重要,可以避免响应欺骗。
比如我查询127.0.0.1,那么C版会自动绑定到127.0.0.1地址。互联网将无法欺骗我的查询的答案。另外,如果我有两个网络接口,一个连接到互联网,一个连接到我的本地网络,IP 为 192.168.0.1,我可以查询本地网络上的解析器,如 172.16.17.18。 C 版本将绑定到地址 192.168.0.1,我将确保答案不是来自互联网。
我怎样才能最好地做到与 C 版本相同?
编辑:解释关于寻找“合适”地址的第二点。
这并不明显,但是如果您将套接字绑定到 (UNSPECIFIED, 0)
,那么当您连接到远程地址时,本地地址将设置为适当的接口地址。 (端口0
表示自动分配一个端口,就像C中的未绑定套接字一样。)您可以在连接成功后在套接字上调用local_addr()
来确认这一点。
对于 POSIX 的复杂性,我深表歉意。 :-)