cloudflare / quiche

🥧 Savoury implementation of the QUIC transport protocol and HTTP/3
https://docs.quic.tech/quiche/
BSD 2-Clause "Simplified" License
9.42k stars 713 forks source link

How does the server use multiple threads to process multiple connections? #1505

Open zhining-lu opened 1 year ago

zhining-lu commented 1 year ago

How does the server use multiple threads to process multiple connections? Now the server only has one thread to process the sending and receiving data of all connections

ljluestc commented 1 month ago

use std::net::{SocketAddr, UdpSocket};
use std::sync::Arc;
use std::thread;
use std::sync::mpsc::{channel, Sender, Receiver};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Bind the server to a specific address
    let bind_addr: SocketAddr = "0.0.0.0:8080".parse()?; // Replace with your desired address and port
    let socket = Arc::new(UdpSocket::bind(bind_addr)?);

    println!("Server running on {}", bind_addr);

    // Use a thread pool or channel to communicate between threads
    let (tx, rx): (Sender<SocketAddr>, Receiver<SocketAddr>) = channel();

    // Create a thread pool, or alternatively spawn a new thread for each connection
    for _ in 0..4 { // Create 4 worker threads
        let socket = Arc::clone(&socket);
        let rx = rx.clone();

        thread::spawn(move || {
            // Each thread will process connections from the receiver channel
            loop {
                if let Ok(client_addr) = rx.recv() {
                    println!("Processing client at {}", client_addr);

                    let mut buf = [0; 1500];
                    match socket.recv_from(&mut buf) {
                        Ok((size, addr)) => {
                            // Echo back to the client
                            println!("Received {} bytes from {}", size, addr);
                            socket.send_to(&buf[..size], addr).unwrap();
                        },
                        Err(e) => {
                            println!("Error receiving from {}: {}", client_addr, e);
                        }
                    }
                }
            }
        });
    }

    // Main loop to handle incoming connections and distribute them to worker threads
    loop {
        let mut buf = [0; 1500];
        if let Ok((size, client_addr)) = socket.recv_from(&mut buf) {
            println!("Received data from client at {}", client_addr);

            // Send the client address to the worker thread for processing
            tx.send(client_addr).unwrap();
        }
    }
}