pub struct UdpSocket(_);
Expand description
UDP 套接字。
通过将 UdpSocket
绑定到一个套接字地址来创建 UdpSocket
之后,数据可以是 发送到 和 从哪里接收 任何其他套接字地址。
尽管 UDP 是无连接协议,但是此实现提供了一个接口,用于设置一个地址,在该地址处应发送和接收数据。
使用 connect
设置远程地址后,可以使用 send
和 recv
向该地址发送数据和从该地址接收数据。
如 IETF RFC 768 中的用户数据报协议规范中所述,UDP 是无序,不可靠的协议。有关 TCP 原语,请参考 TcpListener
和 TcpStream
。
Examples
use std::net::UdpSocket;
fn main() -> std::io::Result<()> {
{
let socket = UdpSocket::bind("127.0.0.1:34254")?;
// 在套接字上接收单个数据报消息。
// 如果 `buf` 太小而无法容纳该消息,它将被切断。
let mut buf = [0; 10];
let (amt, src) = socket.recv_from(&mut buf)?;
// 将 `buf` 声明为接收数据的切片,并将反向数据发送回原点。
let buf = &mut buf[..amt];
buf.reverse();
socket.send_to(buf, &src)?;
} // 套接字在这里关闭
Ok(())
}
RunImplementations§
source§impl UdpSocket
impl UdpSocket
sourcepub fn bind<A: ToSocketAddrs>(addr: A) -> Result<UdpSocket>
pub fn bind<A: ToSocketAddrs>(addr: A) -> Result<UdpSocket>
从给定的地址创建一个 UDP 套接字。
地址类型可以是 ToSocketAddrs
trait 的任何实现者。有关具体的例子,请参见其文档。
如果 addr
产生多个地址,则将使用每个地址尝试 bind
,直到一个成功并返回套接字为止。
如果没有一个地址成功创建套接字,则返回上一次尝试返回的错误 (最后一个地址)。
Examples
创建绑定到 127.0.0.1:3400
的 UDP 套接字:
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:3400").expect("couldn't bind to address");
Run创建绑定到 127.0.0.1:3400
的 UDP 套接字。
如果套接字无法绑定到该地址,请创建绑定到 127.0.0.1:3401
的 UDP 套接字:
use std::net::{SocketAddr, UdpSocket};
let addrs = [
SocketAddr::from(([127, 0, 0, 1], 3400)),
SocketAddr::from(([127, 0, 0, 1], 3401)),
];
let socket = UdpSocket::bind(&addrs[..]).expect("couldn't bind to address");
Run创建绑定到操作系统在 127.0.0.1
分配的端口的 UDP 套接字。
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:0").unwrap();
Runsourcepub fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)>
pub fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)>
在套接字上接收单个数据报消息。 成功时,返回读取的字节数和源。
必须使用足够大的有效字节数组 buf
来调用函数,以容纳消息字节。
如果消息太长而无法容纳在提供的缓冲区中,则多余的字节可能会被丢弃。
Examples
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
let mut buf = [0; 10];
let (number_of_bytes, src_addr) = socket.recv_from(&mut buf)
.expect("Didn't receive data");
let filled_buf = &mut buf[..number_of_bytes];
Run1.18.0 · sourcepub fn peek_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)>
pub fn peek_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)>
在套接字上接收单个数据报消息,而无需将其从队列中删除。 成功时,返回读取的字节数和源。
必须使用足够大的有效字节数组 buf
来调用函数,以容纳消息字节。
如果消息太长而无法容纳在提供的缓冲区中,则多余的字节可能会被丢弃。
连续调用返回相同的数据。
这是通过将 MSG_PEEK
作为标志传递到底层的 recvfrom
系统调用来实现的。
不要使用此函数来实现繁忙等待,而应使用 libc::poll
来同步一个或多个套接字上的 IO 事件。
Examples
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
let mut buf = [0; 10];
let (number_of_bytes, src_addr) = socket.peek_from(&mut buf)
.expect("Didn't receive data");
let filled_buf = &mut buf[..number_of_bytes];
Runsourcepub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A) -> Result<usize>
pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A) -> Result<usize>
将套接字上的数据发送到给定的地址。成功时,返回写入的字节数。
地址类型可以是 ToSocketAddrs
trait 的任何实现者。有关具体的例子,请参见其文档。
addr
可以产生多个地址,但是 send_to
只会将数据发送到 addr
产生的第一个地址。
当本地套接字的 IP 版本与 ToSocketAddrs
返回的 IP 版本不匹配时,这将返回错误。
有关更多详细信息,请参见 Issue #34202。
Examples
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
socket.send_to(&[0; 10], "127.0.0.1:4242").expect("couldn't send data");
Run1.40.0 · sourcepub fn peer_addr(&self) -> Result<SocketAddr>
pub fn peer_addr(&self) -> Result<SocketAddr>
返回此套接字连接到的远程对等方的套接字地址。
Examples
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
socket.connect("192.168.0.1:41203").expect("couldn't connect to address");
assert_eq!(socket.peer_addr().unwrap(),
SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 41203)));
Run如果未连接套接字,它将返回 NotConnected
错误。
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
assert_eq!(socket.peer_addr().unwrap_err().kind(),
std::io::ErrorKind::NotConnected);
Runsourcepub fn local_addr(&self) -> Result<SocketAddr>
pub fn local_addr(&self) -> Result<SocketAddr>
1.4.0 · sourcepub fn set_read_timeout(&self, dur: Option<Duration>) -> Result<()>
pub fn set_read_timeout(&self, dur: Option<Duration>) -> Result<()>
将读取超时设置为指定的超时。
如果指定的值为 None
,则 read
调用将无限期阻塞。
如果将零 Duration
传递给此方法,则返回 Err
。
特定于平台的行为
由于设置此选项而导致读取超时时,平台可能会返回不同的错误代码。
例如,Unix 通常返回类型为 WouldBlock
的错误,但是 Windows 可能返回 TimedOut
。
Examples
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
socket.set_read_timeout(None).expect("set_read_timeout call failed");
Runuse std::io;
use std::net::UdpSocket;
use std::time::Duration;
let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
let err = result.unwrap_err();
assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
Run1.4.0 · sourcepub fn set_write_timeout(&self, dur: Option<Duration>) -> Result<()>
pub fn set_write_timeout(&self, dur: Option<Duration>) -> Result<()>
将写超时设置为指定的超时。
如果指定的值为 None
,则 write
调用将无限期阻塞。
如果将零 Duration
传递给此方法,则返回 Err
。
特定于平台的行为
由于设置此选项而导致写超时时,平台可能会返回不同的错误代码。
例如,Unix 通常返回类型为 WouldBlock
的错误,但是 Windows 可能返回 TimedOut
。
Examples
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
socket.set_write_timeout(None).expect("set_write_timeout call failed");
Runuse std::io;
use std::net::UdpSocket;
use std::time::Duration;
let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
let err = result.unwrap_err();
assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
Run1.4.0 · sourcepub fn read_timeout(&self) -> Result<Option<Duration>>
pub fn read_timeout(&self) -> Result<Option<Duration>>
1.4.0 · sourcepub fn write_timeout(&self) -> Result<Option<Duration>>
pub fn write_timeout(&self) -> Result<Option<Duration>>
1.9.0 · sourcepub fn set_broadcast(&self, broadcast: bool) -> Result<()>
pub fn set_broadcast(&self, broadcast: bool) -> Result<()>
1.9.0 · sourcepub fn broadcast(&self) -> Result<bool>
pub fn broadcast(&self) -> Result<bool>
获取此套接字的 SO_BROADCAST
选项的值。
有关此选项的更多信息,请参见 UdpSocket::set_broadcast
。
Examples
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
socket.set_broadcast(false).expect("set_broadcast call failed");
assert_eq!(socket.broadcast().unwrap(), false);
Run1.9.0 · sourcepub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> Result<()>
pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> Result<()>
1.9.0 · sourcepub fn multicast_loop_v4(&self) -> Result<bool>
pub fn multicast_loop_v4(&self) -> Result<bool>
获取此套接字的 IP_MULTICAST_LOOP
选项的值。
有关此选项的更多信息,请参见 UdpSocket::set_multicast_loop_v4
。
Examples
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
socket.set_multicast_loop_v4(false).expect("set_multicast_loop_v4 call failed");
assert_eq!(socket.multicast_loop_v4().unwrap(), false);
Run1.9.0 · sourcepub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> Result<()>
pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> Result<()>
设置此套接字的 IP_MULTICAST_TTL
选项的值。
指示此套接字的传出多播数据包的生存时间值。 默认值为 1,这意味着除非明确请求,否则多播数据包不会离开本地网络。
请注意,这可能对 IPv6 套接字没有任何影响。
Examples
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
socket.set_multicast_ttl_v4(42).expect("set_multicast_ttl_v4 call failed");
Run1.9.0 · sourcepub fn multicast_ttl_v4(&self) -> Result<u32>
pub fn multicast_ttl_v4(&self) -> Result<u32>
获取此套接字的 IP_MULTICAST_TTL
选项的值。
有关此选项的更多信息,请参见 UdpSocket::set_multicast_ttl_v4
。
Examples
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
socket.set_multicast_ttl_v4(42).expect("set_multicast_ttl_v4 call failed");
assert_eq!(socket.multicast_ttl_v4().unwrap(), 42);
Run1.9.0 · sourcepub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> Result<()>
pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> Result<()>
1.9.0 · sourcepub fn multicast_loop_v6(&self) -> Result<bool>
pub fn multicast_loop_v6(&self) -> Result<bool>
获取此套接字的 IPV6_MULTICAST_LOOP
选项的值。
有关此选项的更多信息,请参见 UdpSocket::set_multicast_loop_v6
。
Examples
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
socket.set_multicast_loop_v6(false).expect("set_multicast_loop_v6 call failed");
assert_eq!(socket.multicast_loop_v6().unwrap(), false);
Run1.9.0 · sourcepub fn ttl(&self) -> Result<u32>
pub fn ttl(&self) -> Result<u32>
获取此套接字的 IP_TTL
选项的值。
有关此选项的更多信息,请参见 UdpSocket::set_ttl
。
Examples
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
socket.set_ttl(42).expect("set_ttl call failed");
assert_eq!(socket.ttl().unwrap(), 42);
Run1.9.0 · sourcepub fn join_multicast_v4(
&self,
multiaddr: &Ipv4Addr,
interface: &Ipv4Addr
) -> Result<()>
pub fn join_multicast_v4( &self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr ) -> Result<()>
执行 IP_ADD_MEMBERSHIP
类型的操作。
此函数为此套接字指定一个新的多播组。
该地址必须是有效的多播地址,而 interface
是系统应加入多播组的本地接口的地址。
如果等于 INADDR_ANY
,则系统选择适当的接口。
1.9.0 · sourcepub fn join_multicast_v6(
&self,
multiaddr: &Ipv6Addr,
interface: u32
) -> Result<()>
pub fn join_multicast_v6( &self, multiaddr: &Ipv6Addr, interface: u32 ) -> Result<()>
执行 IPV6_ADD_MEMBERSHIP
类型的操作。
此函数为此套接字指定一个新的多播组。
该地址必须是有效的多播地址,并且 interface
是接口到 join/leave 的索引 (或 0 表示任何接口)。
1.9.0 · sourcepub fn leave_multicast_v4(
&self,
multiaddr: &Ipv4Addr,
interface: &Ipv4Addr
) -> Result<()>
pub fn leave_multicast_v4( &self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr ) -> Result<()>
执行 IP_DROP_MEMBERSHIP
类型的操作。
有关此选项的更多信息,请参见 UdpSocket::join_multicast_v4
。
1.9.0 · sourcepub fn leave_multicast_v6(
&self,
multiaddr: &Ipv6Addr,
interface: u32
) -> Result<()>
pub fn leave_multicast_v6( &self, multiaddr: &Ipv6Addr, interface: u32 ) -> Result<()>
执行 IPV6_DROP_MEMBERSHIP
类型的操作。
有关此选项的更多信息,请参见 UdpSocket::join_multicast_v6
。
1.9.0 · sourcepub fn take_error(&self) -> Result<Option<Error>>
pub fn take_error(&self) -> Result<Option<Error>>
获取此套接字上 SO_ERROR
选项的值。
这将检索底层套接字中存储的错误,从而清除进程中的字段。 这对于检查两次调用之间的错误很有用。
Examples
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
match socket.take_error() {
Ok(Some(error)) => println!("UdpSocket error: {error:?}"),
Ok(None) => println!("No error"),
Err(error) => println!("UdpSocket.take_error failed: {error:?}"),
}
Run1.9.0 · sourcepub fn connect<A: ToSocketAddrs>(&self, addr: A) -> Result<()>
pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> Result<()>
将此 UDP 套接字连接到远程地址,从而允许使用 send
和 recv
系统调用来发送数据,并且还应用过滤器以仅接收来自指定地址的数据。
如果 addr
产生多个地址,则 connect
将尝试使用每个地址,直到底层 OS 函数没有返回错误为止。
请注意,通常,成功的 connect
调用不会指定有远程服务器在端口上侦听,而是仅在第一次发送后才检测到此错误。
如果操作系统为每个指定的地址返回错误,则返回从上次连接尝试 (最后一个地址) 返回的错误。
Examples
创建绑定到 127.0.0.1:3400
的 UDP 套接字并将该套接字连接到
127.0.0.1:8080
:
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:3400").expect("couldn't bind to address");
socket.connect("127.0.0.1:8080").expect("connect function failed");
Run与 TCP 情况不同,将地址数组传递给 UDP 套接字的 connect
函数不是一件有用的事情:在没有应用程序发送数据的情况下,操作系统将无法确定是否有人在监听远程地址。
1.9.0 · sourcepub fn send(&self, buf: &[u8]) -> Result<usize>
pub fn send(&self, buf: &[u8]) -> Result<usize>
将套接字上的数据发送到它所连接的远程地址。
UdpSocket::connect
将把这个套接字连接到一个远程地址。
如果未连接套接字,则此方法将失败。
Examples
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
socket.connect("127.0.0.1:8080").expect("connect function failed");
socket.send(&[0, 1, 2]).expect("couldn't send message");
Run1.9.0 · sourcepub fn recv(&self, buf: &mut [u8]) -> Result<usize>
pub fn recv(&self, buf: &mut [u8]) -> Result<usize>
从套接字连接到的远程地址在套接字上接收单个数据报消息。 成功时,返回读取的字节数。
必须使用足够大的有效字节数组 buf
来调用函数,以容纳消息字节。
如果消息太长而无法容纳在提供的缓冲区中,则多余的字节可能会被丢弃。
UdpSocket::connect
将把这个套接字连接到一个远程地址。
如果未连接套接字,则此方法将失败。
Examples
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
socket.connect("127.0.0.1:8080").expect("connect function failed");
let mut buf = [0; 10];
match socket.recv(&mut buf) {
Ok(received) => println!("received {received} bytes {:?}", &buf[..received]),
Err(e) => println!("recv function failed: {e:?}"),
}
Run1.18.0 · sourcepub fn peek(&self, buf: &mut [u8]) -> Result<usize>
pub fn peek(&self, buf: &mut [u8]) -> Result<usize>
从套接字所连接的远程地址接收套接字上的单个数据报,而不会从输入队列中删除消息。 成功时,返回偷看的字节数。
必须使用足够大的有效字节数组 buf
来调用函数,以容纳消息字节。
如果消息太长而无法容纳在提供的缓冲区中,则多余的字节可能会被丢弃。
连续调用返回相同的数据。这是通过将 MSG_PEEK
作为标志传递给底层的 recv
系统调用来实现的。
不要使用此函数来实现繁忙等待,而应使用 libc::poll
来同步一个或多个套接字上的 IO 事件。
UdpSocket::connect
将把这个套接字连接到一个远程地址。如果未连接套接字,则此方法将失败。
Errors
如果未连接套接字,则此方法将失败。connect
方法会将此套接字连接到远程地址。
Examples
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
socket.connect("127.0.0.1:8080").expect("connect function failed");
let mut buf = [0; 10];
match socket.peek(&mut buf) {
Ok(received) => println!("received {received} bytes"),
Err(e) => println!("peek function failed: {e:?}"),
}
Run1.9.0 · sourcepub fn set_nonblocking(&self, nonblocking: bool) -> Result<()>
pub fn set_nonblocking(&self, nonblocking: bool) -> Result<()>
将此 UDP 套接字移入或移出非阻塞模式。
这将导致 recv
,recv_from
,send
和 send_to
操作变为非阻塞,即立即从其调用中返回。
如果 IO 操作成功,则返回 Ok
,并且不需要进一步的操作。
如果 IO 操作无法完成,需要重试,则返回类型为 io::ErrorKind::WouldBlock
的错误。
在 Unix 平台上,调用此方法相当于调用 fcntl
FIONBIO
。
在 Windows 上,调用此方法对应于调用 ioctlsocket
FIONBIO
。
Examples
创建绑定到 127.0.0.1:7878
的 UDP 套接字,并以非阻塞模式读取字节:
use std::io;
use std::net::UdpSocket;
let socket = UdpSocket::bind("127.0.0.1:7878").unwrap();
socket.set_nonblocking(true).unwrap();
let mut buf = [0; 10];
let (num_bytes_read, _) = loop {
match socket.recv_from(&mut buf) {
Ok(n) => break n,
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
// 等待网络套接字就绪,通常通过平台特定的 API (例如 epoll 或 IOCP) 实现
wait_for_fd();
}
Err(e) => panic!("encountered IO error: {e}"),
}
};
println!("bytes: {:?}", &buf[..num_bytes_read]);
Run