-
Notifications
You must be signed in to change notification settings - Fork 29
How do we multicast using Rust's net? #81
Description
I'm using
rustc1.30.1. I am doing everything on the same machine.
Rust's net provides a way to a join a multicast group, using join_multicast_v4. But I am unable to create an example, using just net, where I am able to multicast, that is, send a message to a multicast group B, and all sockets associated with B receive the message.
Here's the code I am using to try to implement multicasting in Rust using just net.
use std::net::Ipv4Addr;
use std::net::UdpSocket;
use std::str::FromStr;
use std::thread;
use std::time::Duration;
fn main() {
// Host of group A.
let proposers_host = "239.0.0.1";
// Host of group B.
let acceptors_host = "239.0.0.1";
let acceptors_address = "239.0.0.1:7000";
let join_handle1: thread::JoinHandle<_> = thread::spawn(move || {
println!("{}", "Spawning 1st thread");
let socket = UdpSocket::bind("0.0.0.0:0").expect("Couldn't bind proposer UDP socket");
// Does NOT work even if I uncomment the following.
// socket
// .set_multicast_loop_v4(true)
// .expect("Could not enable multicast loop, to send packets back to the local socket");
// This socket joined this group. Let's call this group A.
socket
.join_multicast_v4(
&Ipv4Addr::from_str(proposers_host).unwrap(),
&Ipv4Addr::UNSPECIFIED,
).expect("Could not join multicast group A");
for i in 1..10 {
// Send message to the acceptors that joined the multicast group B.
socket
.send_to(&[i], acceptors_address)
.expect("couldn't send data");
println!("Sent message: {:?}\n---\n", i);
thread::sleep(Duration::from_millis(1));
}
});
let join_handle2: thread::JoinHandle<_> = thread::spawn(move || {
println!("{}", "Spawning 2nd thread");
let socket = UdpSocket::bind("0.0.0.0:0").expect("Could not bind acceptor 1 UDP socket");
// Joining group B.
socket
.join_multicast_v4(
&Ipv4Addr::from_str(acceptors_host).unwrap(),
&Ipv4Addr::UNSPECIFIED,
).expect("Could not join multicast group B");
let mut buf = [0; 10];
let mut c = 0;
loop {
let (number_of_bytes, src_addr) =
socket.recv_from(&mut buf).expect("Didn't receive data");
let filled_buf = &mut buf[..number_of_bytes];
println!("I am the 2nd socket");
println!("Message received from address = {:?}", src_addr);
println!("Contents of the message = {:?}\n---\n", filled_buf);
thread::sleep(Duration::from_millis(1));
c += 1;
if c == 5 {
break;
}
}
});
let join_handle3: thread::JoinHandle<_> = thread::spawn(move || {
println!("{}", "Spawning 3rd thread");
let socket = UdpSocket::bind("0.0.0.0:0").expect("Could not bind acceptor 2 UDP socket");
socket
.join_multicast_v4(
&Ipv4Addr::from_str(acceptors_host).unwrap(),
&Ipv4Addr::UNSPECIFIED,
).expect("Could not join multicast group B");
let mut buf = [0; 10];
loop {
let (number_of_bytes, src_addr) =
socket.recv_from(&mut buf).expect("Didn't receive data");
let filled_buf = &mut buf[..number_of_bytes];
println!("I am the 3rd socket");
println!("Message received from address = {:?}", src_addr);
println!("Contents of the message = {:?}\n---\n", filled_buf);
thread::sleep(Duration::from_millis(1));
}
});
println!("{}", "At the end");
join_handle1.join().unwrap();
join_handle2.join().unwrap();
join_handle3.join().unwrap();
}It's not clear to me why Rust's net provides a method join_multicast_v4, but the example above does not work as expected, i.e. the "acceptors" do not receive anything!
I can't bind two sockets to the same port (at least, locally, and I am doing this locally, but eventually acceptors could be in different machines). If I bind socket 2 and 3 to the same port 7000, one of the acceptors (either 2 or 3) receives the messages, but the other panics because I can't bind two sockets to the same port. You can test this behaviour by changing the lines above (in the 2nd and 3rd socket)
let socket = UdpSocket::bind("0.0.0.0:0").expect("...");
to, e.g.,
let socket = UdpSocket::bind("0.0.0.0:7000").expect("...");
And you will get a panic, as I just explained.
So, how do I multicast using Rust's net? Can you please provide a simple example where there are multiple receivers (or acceptors) that receive the message sent by the same sender?