Implementing Request-Response Pattern with Channels in Rust
Rust Error Propagation: Exercise-9 with Solution
Write a Rust program to implement a request-response pattern using channels. Create one thread to handle requests and another thread to handle responses. When a request is received, the handler thread processes it and sends a response back through the channel.
Sample Solution:
Rust Code:
use std::sync::{mpsc, Arc, Mutex};
use std::thread;
fn main() {
// Create channels for communication between request and response handlers
let (request_sender, request_receiver) = mpsc::channel(); // Create a channel for sending requests
let (response_sender, response_receiver) = mpsc::channel(); // Create a channel for sending responses
let response_receiver = Arc::new(Mutex::new(response_receiver)); // Wrap the response receiver in an Arc and a Mutex for safe sharing among threads
// Spawn a thread to handle requests
let request_handler = thread::spawn(move || { // Spawn a new thread
for request in request_receiver { // Iterate over received requests
// Process the request (e.g., simulate processing time)
let processed_request = format!("Processed: {}", request);
// Send the response back through the channel
response_sender.send(processed_request).unwrap();
}
});
// Spawn a thread to handle responses
let cloned_response_receiver = Arc::clone(&response_receiver); // Clone the Arc to share ownership with the response handler thread
let response_handler = thread::spawn(move || { // Spawn a new thread
// Get the inner receiver from the Arc
let receiver = cloned_response_receiver.lock().unwrap(); // Lock the mutex to access the receiver
for response in receiver.iter() { // Iterate over received responses
// Handle the response (e.g., print it)
println!("Received response: {}", response);
}
});
// Simulate sending requests
for i in 0..5 {
// Send a request through the channel
request_sender.send(i.to_string()).unwrap();
// Receive the response
let response = response_receiver.lock().unwrap().recv().unwrap();
// Print the received response
println!("Received response to request {}: {}", i, response);
}
// Wait for request and response handler threads to finish
request_handler.join().unwrap();
response_handler.join().unwrap();
}
Output:
Received response to request 0: Processed: 0 Received response to request 1: Processed: 1 Received response to request 2: Processed: 2 Received response to request 3: Processed: 3 Received response to request 4: Processed: 4
Explanation:
In the exercise above,
- Two channels are created: 'request_sender' and 'request_receiver' for handling requests, and 'response_sender' and 'response_receiver' for handling responses. The 'response_receiver' is wrapped in an 'Arc' and a 'Mutex' for safe sharing among threads.
- A thread is spawned to handle requests ('request_handler'). It listens for requests from the 'request_receiver', processes them (e.g., simulates processing time), and sends back the responses through the 'response_sender'.
- Another thread is spawned to handle responses ('response_handler'). It locks the 'response_receiver' mutex, iterates over received responses, and handles them (e.g., prints them).
- The main thread simulates sending requests by iterating over a range of values. For each value, it sends a request through the 'request_sender', waits for the response by receiving it from the 'response_receiver', and prints the received response.
- Finally, the main thread waits for both the request and response handler threads to finish using "join()".
Rust Code Editor:
Previous: Demonstrating Buffered Channels in Rust.
What is the difficulty level of this exercise?
Test your Programming skills with w3resource's quiz.
It will be nice if you may share this link in any developer community or anywhere else, from where other developers may find this content. Thanks.
https://www.w3resource.com/rust/channels/rust-message-passing-exercise-9.php
- Weekly Trends and Language Statistics
- Weekly Trends and Language Statistics