w3resource

Rust Concurrent Web Server with Threads

Rust Threads and Synchronization: Exercise-5 with Solution

Write a Rust program that simulates a simple concurrent web server using threads.

Sample Solution:

Rust Code:

use std::net::{TcpListener, TcpStream}; // Import necessary networking modules
use std::io::{Read, Write}; // Import modules for reading from and writing to streams
use std::thread; // Import module for creating threads

// Define a function to handle each client connection
fn handle_client(mut stream: TcpStream) {
    let mut buffer = [0; 512]; // Create a buffer to store incoming data

    // Read data from the stream into the buffer
    stream.read(&mut buffer).unwrap();

    // Convert the data to a string
    let request = String::from_utf8_lossy(&buffer[..]);

    // Print the received request
    println!("Received request: {}", request);

    // Define a simple HTTP response
    let response = "HTTP/1.1 200 OK\r\n\r\nHello, World!";

    // Write the response back to the client
    stream.write(response.as_bytes()).unwrap();

    // Flush the stream to ensure all data is sent
    stream.flush().unwrap();
}

fn main() {
    let listener = TcpListener::bind("127.0.0.1:8080").unwrap(); // Create a TCP listener on localhost port 8080

    println!("Server listening on port 8080...");

    // Accept incoming connections and handle them concurrently using threads
    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                // Spawn a new thread to handle each client connection
                thread::spawn(move || {
                    handle_client(stream); // Call the handle_client function for each client
                });
            }
            Err(e) => {
                // Print an error message if there's an issue accepting a connection
                println!("Error accepting connection: {}", e);
            }
        }
    }
}

Output:

Server listening on port 8080...

Explanation:

In the exercise above,

  • Import the necessary modules from the standard library (std::net, std::io, and std::thread) for handling networking, input/output operations, and concurrency with threads.
  • Next, we define a function called "handle_client()", which takes a 'TcpStream' representing a client connection. Inside this function, we read data from the stream, print the received request, construct a simple HTTP response, and write the response back to the client.
  • In the main function, we create a TCP listener bound to 127.0.0.1:8080, which means it listens for incoming connections on localhost at port 8080.
  • We print a message indicating that the server is listening on port 8080.
  • We enter a loop where we continuously accept incoming connections using the listener.incoming() method. This method returns an iterator of incoming connections represented as Result<TcpStream, std::io::Error>.
  • Inside the loop, for each incoming connection, we spawn a new thread using thread::spawn. This allows us to handle multiple connections concurrently. We pass the incoming 'TcpStream' to the "handle_client()" function in the spawned thread.
  • If there's an error accepting a connection, we print an error message.

Rust Code Editor:

Previous: Rust Program: Matrix Multiplication with Parallel Threads.
Next: Rust Concurrent Task Scheduler with Threads.

What is the difficulty level of this exercise?

Test your Programming skills with w3resource's quiz.



Become a Patron!

Follow us on Facebook and Twitter for latest update.

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/threads_and_synchronization/rust-threads-and-synchronization-exercise-5.php