Implementing Request-Response Pattern with Channels in Rust
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.
- Weekly Trends and Language Statistics
- Weekly Trends and Language Statistics