w3resource

Simulating a Message Passing Network in Rust

Rust Error Propagation: Exercise-5 with Solution

Write a Rust program to simulate a message passing network, where each node communicates with its neighboring nodes through channels. Implement message routing and forwarding between nodes.

Sample Solution:

Rust Code:

use std::sync::{Arc, Mutex};
use std::sync::mpsc;
use std::thread;

const NUM_NODES: usize = 5;

fn main() {
    // Create channels for communication between nodes
    let mut channels = Vec::new();
    for _ in 0..NUM_NODES {
        let (sender, receiver) = mpsc::channel();
        channels.push(Arc::new(Mutex::new((sender, receiver))));
    }

    // Spawn threads for each node
    let mut handles = Vec::new();
    for i in 0..NUM_NODES {
        let _next_node = (i + 1) % NUM_NODES;
        let prev_node = if i == 0 { NUM_NODES - 1 } else { i - 1 };
        
        let sender = Arc::clone(&channels[i]);
        let receiver = Arc::clone(&channels[prev_node]);
        let handle = thread::spawn(move || {
            node(i, sender, receiver);
        });
        handles.push(handle);
    }

    // Send a message from the first node
    let message = "Hello from Node 0!";
    channels[0].lock().unwrap().0.send(message.to_string()).unwrap();

    // Wait for all threads to finish
    for handle in handles {
        handle.join().unwrap();
    }
}

fn node(id: usize, sender: Arc<Mutex<(mpsc::Sender<String>, mpsc::Receiver<String>)>>, receiver: Arc<Mutex<(mpsc::Sender<String>, mpsc::Receiver<String>)>>) {
    loop {
        // Receive message from previous node
        let received_msg = receiver.lock().unwrap().1.recv().unwrap();
        println!("Node {}: Received message: {}", id, received_msg);

        // Forward message to next node
        let forwarded_msg = format!("Forwarded from Node {} to Node {}", id, (id + 1) % NUM_NODES);
        sender.lock().unwrap().0.send(forwarded_msg.clone()).unwrap();
        println!("Node {}: Forwarded message: {}", id, forwarded_msg);
    }
}

Output:

Node 1: Received message: Hello from Node 0!
Node 1: Forwarded message: Forwarded from Node 1 to Node 2
Node 2: Received message: Forwarded from Node 1 to Node 2

Explanation:

In the exercise above,

  • Import necessary modules for synchronization ("Arc", "Mutex"), inter-thread communication ('mpsc'), and multi-threading ('thread').
  • Constants: It defines 'NUM_NODES' as the number of nodes in the network.
  • Main Function:
    • Channel Creation: It creates a vector 'channels' to hold channels for communication between nodes. Each channel consists of a sender and a receiver.
    • Node Threads: It spawns threads for each node in the network. Each thread represents a node and executes the "node()" function. The sender and receiver for each node are obtained from the 'channels' vector, ensuring that each node communicates with its adjacent nodes.
    • Message Sending: It sends a message from the first node (Node 0) to kickstart the communication process.
    • Thread Joining: It waits for all node threads to finish executing before the program exits.
  • Node Function:
    • Message Receiving: It continuously receives messages from the previous node (as determined by the index of the 'channels' vector).
    • Message Forwarding: It forwards the received message to the next node in the network. The message includes information about the current node and the next node it's being forwarded to.

Rust Code Editor:

Previous: Rust Producer-Consumer Pattern with Channels.
Next: Implementing Synchronous Channels in Rust.

What is the difficulty level of this exercise?

Test your Programming skills with w3resource's quiz.



Follow us on Facebook and Twitter for latest update.