Rust lang series episode #32 — tcp server (#rust-series)

in rust-series •  8 years ago  (edited)

Greetings everyone, here comes another Rust lang series episode. Today we will try to create simple TCP server in Rust that will listen at given port and return simple text greeting when connected. Each connection will be handled in special thread.

TCP server simplified implementation

We will use only API from standard library, API related to TCP protocol is part of networking std::net module. Let's take a look at code at first before we break it down.

use std::io::Write;
use std::net::TcpListener;
use std::thread;

fn main() {
    let ip_and_port = "127.0.0.1:1234";
    let listener = TcpListener::bind(ip_and_port).unwrap();

    println!("listening on port 1234 on http://localhost:1234");

    for stream in listener.incoming() {
        thread::spawn(|| {
            let mut stream = stream.unwrap();
            stream.write(b"Hi to all Steemiters!\r\n").unwrap();
        });
    }
}

Output

When you open your browser and open http://localhost:1234 address you'll see this message

Hi to all Steemiters!

You can also check connection from command-line with tools curl or whatever is provided on your OS.

curl localhost:1234

# output
Hi to all Steemiters!
curl: (56) Recv failure: Connection reset by peer

Breaking down

Let's analyze the source code a bit:

First we set ip address and port, we set it to localhost (127.0.0.1) and port to 1234.

std::io::Write provides write method for TcpStream

std::net::TcpListener is basic building component for TCP socket server

bind() method creates TcpListener and binds it to given port

incomming() iterator over received connections

thread::spawn() new thread is created and executes code each TCP stream (connection)

write() sends data to TCPStream

Version with proper error handling

Of course previous version doesn't solve issue handling that can occur on multiple places and just terminate main thread when something bad occurs. Let's try to implement something the a better care for potential errors. Possible implementation could look like this for example.

use std::io::Write;
use std::net::TcpListener;
use std::net::TcpStream;
use std::thread;

fn create_server() -> Option<TcpListener> {
    let ip_and_port = "127.0.0.1:1234";
    let res = TcpListener::bind(ip_and_port);
    match res {
        Ok(listener) => return Some(listener),
        Err(err) => {
            println!("Cannot create server: - {}", err.to_string());
            None
        }
    }
}

fn handle_incoming_stream(mut stream: TcpStream) {
    thread::spawn(move || {
        let write_res = stream.write(b"Hi to all Steemiters!\r\n");
        if let Err(err) = write_res {
            println!("Cannot send data - {}", err.to_string());
        } else {
            println!("Response sent OK");
        }
    });
}

fn main() {
    let server_result = create_server();
    if let Some(listener) = server_result {
        println!("listening on port 1234 on http://localhost:1234");
        for stream_res in listener.incoming() {
            if let Ok(mut stream) = stream_res {
                handle_incoming_stream(stream);
            } else if let Err(err) = stream_res {
                println!("Stream error - {}", err.to_string());
            }
        }
    }
}

Output

When you see this application multiple times you can see for example this error properly handled.

Cannot create server: - Address already in use (os error 98)
Application finished!

Breaking down

Code is just split to mutliple functions to separate concerns and handling related errors. TcpListener and TcpStreams operations returns std::io::Result that we handled on proper places. But in general there is nothing new that should be explained.

Postfix

That's all for now, thank you for your appreciations, feel free to comment and point out possible mistakes (first 24 hours works the best but any time is fine). May Jesus bless your programming skills, use them wisely and see you next time.

Meanwhile you can also check the official documentation for additional related information:

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!