pub struct UdpSocket { /* private fields */ }Expand description
A UDP socket.
UDP is “connectionless”, unlike TCP. Meaning, regardless of what address you’ve bound to, a UdpSocket
is free to communicate with many different remotes. In tokio there are basically two main ways to use UdpSocket:
- one to many:
bindand usesend_toandrecv_fromto communicate with many different addresses - one to one:
connectand associate with a single address, usingwriteandreadto communicate only with that remote address
§Examples
Bind and connect a pair of sockets and send a packet:
use tokio_uring::net::UdpSocket;
use std::net::SocketAddr;
fn main() -> std::io::Result<()> {
tokio_uring::start(async {
let first_addr: SocketAddr = "127.0.0.1:2401".parse().unwrap();
let second_addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();
// bind sockets
let socket = UdpSocket::bind(first_addr.clone()).await?;
let other_socket = UdpSocket::bind(second_addr.clone()).await?;
// connect sockets
socket.connect(second_addr).await.unwrap();
other_socket.connect(first_addr).await.unwrap();
let buf = vec![0; 32];
// write data
let (result, _) = socket.write(b"hello world".as_slice()).submit().await;
result.unwrap();
// read data
let (result, buf) = other_socket.read(buf).await;
let n_bytes = result.unwrap();
assert_eq!(b"hello world", &buf[..n_bytes]);
// write data using send on connected socket
let (result, _) = socket.send(b"hello world via send".as_slice()).await;
result.unwrap();
// read data
let (result, buf) = other_socket.read(buf).await;
let n_bytes = result.unwrap();
assert_eq!(b"hello world via send", &buf[..n_bytes]);
Ok(())
})
}Send and receive packets without connecting:
use tokio_uring::net::UdpSocket;
use std::net::SocketAddr;
fn main() -> std::io::Result<()> {
tokio_uring::start(async {
let first_addr: SocketAddr = "127.0.0.1:2401".parse().unwrap();
let second_addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();
// bind sockets
let socket = UdpSocket::bind(first_addr.clone()).await?;
let other_socket = UdpSocket::bind(second_addr.clone()).await?;
let buf = vec![0; 32];
// write data
let (result, _) = socket.send_to(b"hello world".as_slice(), second_addr).await;
result.unwrap();
// read data
let (result, buf) = other_socket.recv_from(buf).await;
let (n_bytes, addr) = result.unwrap();
assert_eq!(addr, first_addr);
assert_eq!(b"hello world", &buf[..n_bytes]);
Ok(())
})
}Implementations§
Source§impl UdpSocket
impl UdpSocket
Sourcepub async fn bind(socket_addr: SocketAddr) -> Result<UdpSocket>
pub async fn bind(socket_addr: SocketAddr) -> Result<UdpSocket>
Sourcepub fn local_addr(&self) -> Result<SocketAddr>
pub fn local_addr(&self) -> Result<SocketAddr>
Returns the local address to which this UDP socket is bound.
This can be useful, for example, when binding to port 0 to figure out which port was actually bound.
§Examples
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use tokio_uring::net::UdpSocket;
tokio_uring::start(async {
let socket = UdpSocket::bind("127.0.0.1:8080".parse().unwrap()).await.unwrap();
let addr = socket.local_addr().expect("Couldn't get local address");
assert_eq!(addr, SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080)));
});Sourcepub fn from_std(socket: UdpSocket) -> Self
pub fn from_std(socket: UdpSocket) -> Self
Creates new UdpSocket from a previously bound std::net::UdpSocket.
This function is intended to be used to wrap a UDP socket from the standard library in the tokio-uring equivalent. The conversion assumes nothing about the underlying socket; it is left up to the user to decide what socket options are appropriate for their use case.
This can be used in conjunction with socket2’s Socket interface to
configure a socket before it’s handed off, such as setting options like
reuse_address or binding to multiple addresses.
§Example
use socket2::{Protocol, Socket, Type};
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use tokio_uring::net::UdpSocket;
fn main() -> std::io::Result<()> {
tokio_uring::start(async {
let std_addr: SocketAddr = "127.0.0.1:2401".parse().unwrap();
let second_addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();
let sock = Socket::new(socket2::Domain::IPV4, Type::DGRAM, Some(Protocol::UDP))?;
sock.set_reuse_port(true)?;
sock.set_nonblocking(true)?;
sock.bind(&std_addr.into())?;
let std_socket = UdpSocket::from_std(sock.into());
let other_socket = UdpSocket::bind(second_addr).await?;
let buf = vec![0; 32];
// write data
let (result, _) = std_socket
.send_to(b"hello world".as_slice(), second_addr)
.await;
result.unwrap();
// read data
let (result, buf) = other_socket.recv_from(buf).await;
let (n_bytes, addr) = result.unwrap();
assert_eq!(addr, std_addr);
assert_eq!(b"hello world", &buf[..n_bytes]);
Ok(())
})
}Sourcepub async fn connect(&self, socket_addr: SocketAddr) -> Result<()>
pub async fn connect(&self, socket_addr: SocketAddr) -> Result<()>
“Connects” this UDP socket to a remote address.
This enables write and read syscalls to be used on this instance.
It also constrains the read to receive data only from the specified remote peer.
Note: UDP is connectionless, so a successful connect call does not execute
a handshake or validation of the remote peer of any kind.
Any errors would not be detected until the first send.
Sourcepub async fn send<T: BoundedBuf>(&self, buf: T) -> BufResult<usize, T>
pub async fn send<T: BoundedBuf>(&self, buf: T) -> BufResult<usize, T>
Sends data on the connected socket
On success, returns the number of bytes written.
Sourcepub async fn send_to<T: BoundedBuf>(
&self,
buf: T,
socket_addr: SocketAddr,
) -> BufResult<usize, T>
pub async fn send_to<T: BoundedBuf>( &self, buf: T, socket_addr: SocketAddr, ) -> BufResult<usize, T>
Sends data on the socket to the given address.
On success, returns the number of bytes written.
Sourcepub async fn send_zc<T: BoundedBuf>(&self, buf: T) -> BufResult<usize, T>
pub async fn send_zc<T: BoundedBuf>(&self, buf: T) -> BufResult<usize, T>
Sends data on the socket. Will attempt to do so without intermediate copies.
On success, returns the number of bytes written.
See the linux kernel docs for a discussion on when this might be appropriate. In particular:
Copy avoidance is not a free lunch. As implemented, with page pinning, it replaces per byte copy cost with page accounting and completion notification overhead. As a result, zero copy is generally only effective at writes over around 10 KB.
Note: Using fixed buffers #54, avoids the page-pinning overhead
Sourcepub async fn sendmsg<T: BoundedBuf, U: BoundedBuf>(
&self,
io_slices: Vec<T>,
socket_addr: Option<SocketAddr>,
msg_control: Option<U>,
) -> (Result<usize>, Vec<T>, Option<U>)
pub async fn sendmsg<T: BoundedBuf, U: BoundedBuf>( &self, io_slices: Vec<T>, socket_addr: Option<SocketAddr>, msg_control: Option<U>, ) -> (Result<usize>, Vec<T>, Option<U>)
Sends a message on the socket using a msghdr.
Returns a tuple of:
- Result containing bytes written on success
- The original
io_slicesVec<T> - The original
msg_contolOption<U>
Consider using Self::sendmsg_zc for a zero-copy alternative.
Sourcepub async fn sendmsg_zc<T: BoundedBuf, U: BoundedBuf>(
&self,
io_slices: Vec<T>,
socket_addr: Option<SocketAddr>,
msg_control: Option<U>,
) -> (Result<usize>, Vec<T>, Option<U>)
pub async fn sendmsg_zc<T: BoundedBuf, U: BoundedBuf>( &self, io_slices: Vec<T>, socket_addr: Option<SocketAddr>, msg_control: Option<U>, ) -> (Result<usize>, Vec<T>, Option<U>)
Sends a message on the socket using a msghdr.
Returns a tuple of:
- Result containing bytes written on success
- The original
io_slicesVec<T> - The original
msg_contolOption<U>
See the linux kernel docs for a discussion on when this might be appropriate. In particular:
Copy avoidance is not a free lunch. As implemented, with page pinning, it replaces per byte copy cost with page accounting and completion notification overhead. As a result, zero copy is generally only effective at writes over around 10 KB.
Can be used with socket_addr: None on connected sockets, which can have performance benefits if multiple datagrams are sent to the same destination address.
Sourcepub async fn recv_from<T: BoundedBufMut>(
&self,
buf: T,
) -> BufResult<(usize, SocketAddr), T>
pub async fn recv_from<T: BoundedBufMut>( &self, buf: T, ) -> BufResult<(usize, SocketAddr), T>
Receives a single datagram message on the socket.
On success, returns the number of bytes read and the origin.
Sourcepub async fn recvmsg<T: BoundedBufMut>(
&self,
buf: Vec<T>,
) -> BufResult<(usize, SocketAddr), Vec<T>>
pub async fn recvmsg<T: BoundedBufMut>( &self, buf: Vec<T>, ) -> BufResult<(usize, SocketAddr), Vec<T>>
Receives a single datagram message on the socket, into multiple buffers
On success, returns the number of bytes read and the origin.
Sourcepub async fn read<T: BoundedBufMut>(&self, buf: T) -> BufResult<usize, T>
pub async fn read<T: BoundedBufMut>(&self, buf: T) -> BufResult<usize, T>
Reads a packet of data from the socket into the buffer.
Returns the original buffer and quantity of data read.
Sourcepub async fn read_fixed<T>(&self, buf: T) -> BufResult<usize, T>where
T: BoundedBufMut<BufMut = FixedBuf>,
pub async fn read_fixed<T>(&self, buf: T) -> BufResult<usize, T>where
T: BoundedBufMut<BufMut = FixedBuf>,
Receives a single datagram message into a registered buffer.
Like read, but using a pre-mapped buffer
registered with FixedBufRegistry.
§Errors
In addition to errors that can be reported by read,
this operation fails if the buffer is not registered in the
current tokio-uring runtime.
Sourcepub fn write<T: BoundedBuf>(&self, buf: T) -> UnsubmittedWrite<T>
pub fn write<T: BoundedBuf>(&self, buf: T) -> UnsubmittedWrite<T>
Writes data into the socket from the specified buffer.
Returns the original buffer and quantity of data written.
Sourcepub async fn write_fixed<T>(&self, buf: T) -> BufResult<usize, T>where
T: BoundedBuf<Buf = FixedBuf>,
pub async fn write_fixed<T>(&self, buf: T) -> BufResult<usize, T>where
T: BoundedBuf<Buf = FixedBuf>,
Writes data into the socket from a registered buffer.
Like write, but using a pre-mapped buffer
registered with FixedBufRegistry.
§Errors
In addition to errors that can be reported by write,
this operation fails if the buffer is not registered in the
current tokio-uring runtime.