Weekly Rust Trivia is a problem-oriented series of articles that assist developers while learning Rust. Every article solves simple, everyday development tasks using the Rust standard library or leveraging popular and proven crates.
Question: How to create a TCP server in Rust?
We can use the io
and net
and thread
modules from Rust standard library this trivia.
use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream};
use std::thread;
fn handle(mut stream: TcpStream) {
// 64 KB buffer for demonstration purposes
let mut buffer = [0; 65536];
loop {
let bytes_read = match stream.read(&mut buffer) {
Ok(0) => return, // End of stream
Ok(n) => n,
Err(_) => return, // Error reading from stream
};
// Echo the data back to the client
if let Err(_) = stream.write(&buffer[..bytes_read]) {
return; // Error writing to stream
}
}
}
The handle
function takes in a TcpStream
object representing a client connection.
Inside the function, a buffer
of size 65536 bytes (64 KB) is created to hold the incoming data. The function then enters an infinite loop and reads data from the client into the buffer. If the read
operation returns an error, the function returns immediately.
If the read
operation returns zero (0
), it means that the end of the stream has been reached, and the function returns. If data is successfully read from the client, it is immediately written back to the client as an echo. If the write
operation returns an error, the handle
function will again return immediately.
Now that we walked through the handle
function, we can use the TcpListener
struct and expose our custom echo server on port 8080
. For every incoming connection, we spawn a new thread using the spawn
function of the thread
module:
fn main() -> std::io::Result<()> {
let listener = TcpListener::bind("127.0.0.1:8080")?;
for stream in listener.incoming() {
match stream {
Ok(stream) => {
// Spawn a new thread to handle each incoming connection
thread::spawn(move || handle(stream));
}
Err(e) => {
println!("Error accepting connection: {}", e);
}
}
}
Ok(())
}
We can connect to our custom TCP-Echo server using telnet
:
telnet localhost 8080
# Trying ::1...
# telnet: connect to address ::1: Connection refused
# Trying 127.0.0.1...
# Connected to localhost.
# Escape character is '^]'.
# Hello
# Hello
# Bye
# Bye
# telnet> Connection closed.