[−][src]Crate udp_sas_mio
This crate provides an extension trait for mio::net::UdpSocket
that supports source address
selection for outgoing UDP datagrams. This is useful for implementing a UDP server that binds
multiple network interfaces.
The implementation relies on socket options IP_PKTINFO
(for IPv4) and IPV6_RECVPKTINFO
(for IPv6).
extern crate mio; extern crate udp_sas_mio; use std::net::SocketAddr; use std::time::Duration; use mio::{Events,Interest,Poll,Token}; use mio::net::UdpSocket; use udp_sas_mio::UdpSas; fn main() { demo().unwrap(); } fn demo() -> std::io::Result<()> { let mut buf = [0u8;128]; // Create the server socket and bind it to 0.0.0.0:30012 // // Note: we will use 127.0.0.23 as source/destination address // for our datagrams (to demonstrate the crate features) // let mut srv = UdpSocket::bind_sas("0.0.0.0:30012".parse::<SocketAddr>().unwrap())?; let srv_addr : SocketAddr = "127.0.0.23:30012".parse().unwrap(); // Create the client socket and bind it to an anonymous port // // Note: we will use 127.0.0.45 as source/destination address // for our datagrams (to demonstrate the crate features) // let mut cli = UdpSocket::bind_sas("0.0.0.0:0".parse::<SocketAddr>().unwrap())?; let cli_addr = SocketAddr::new( "127.0.0.45".parse().unwrap(), cli.local_addr().unwrap().port()); assert_ne!(cli_addr.port(), 0); // Messages to be sent let msg1 = "What do you get if you multiply six by nine?"; let msg2 = "Forty-two"; // create the Poll object and register the sockets let mut poll = Poll::new()?; const SRV : Token = Token(0); const CLI : Token = Token(1); poll.registry().register(&mut cli, CLI, Interest::WRITABLE)?; poll.registry().register(&mut srv, SRV, Interest::READABLE)?; let timeout = Some(Duration::from_millis(100)); let mut events = Events::with_capacity(1); loop { let nb = poll.poll(&mut events, timeout)?; assert!(!events.is_empty(), "timeout"); for event in events.iter() { match event.token() { CLI if event.is_writable() => { // send a request (msg1) from the client to the server let nb = cli.send_sas(msg1.as_bytes(), &srv_addr, &cli_addr.ip())?; assert_eq!(nb, msg1.as_bytes().len()); poll.registry().reregister(&mut cli, CLI, Interest::READABLE)?; }, SRV if event.is_readable() => { // receive the request on the server let (nb, peer, local) = srv.recv_sas(&mut buf)?; assert_eq!(peer, cli_addr); assert_eq!(local, srv_addr.ip()); assert_eq!(nb, msg1.as_bytes().len()); assert_eq!(&buf[0..nb], msg1.as_bytes()); poll.registry().reregister(&mut srv, SRV, Interest::WRITABLE)?; }, SRV if event.is_writable() => { // send a reply (msg2) from the server to the client let nb = srv.send_sas(msg2.as_bytes(), &cli_addr, &srv_addr.ip())?; assert_eq!(nb, msg2.as_bytes().len()); }, CLI if event.is_readable() => { // receive the reply on the client let (nb, peer, local) = cli.recv_sas(&mut buf)?; assert_eq!(peer, srv_addr); assert_eq!(local, cli_addr.ip()); assert_eq!(nb, msg2.as_bytes().len()); assert_eq!(&buf[0..nb], msg2.as_bytes()); return Ok(()); }, token => panic!("unexpected token: {:?}", token) } } } }
Traits
UdpSas | An extension trait to support source address selection in |