CODING ACADEMY
Develop TCP/IP servers and clients
Get a better grip on network programming as the indispensable Mihalis Tsoukalos explains how to develop TCP/IP software in Rust.
RUST
Mihalis Tsoukalos is a systems engineer and a technical writer. You can reach him at www.
mtsoukalos.eu and @mactsouk.
OUR EXPERT
Get the code for this tutorial from the Linux Format archive: www. linuxformat. com/archives ?issue=293.
You can learn more about Rust at www. rust-lang.org.
This month we’ll learn how to develop TCP/IP servers and clients in Rust. Creating separate threads for handling client interactions is a common task, especially for TCP services so we’ll assume that you already know about concurrent programming in Rust and are familiar with the use of the thread::spawn() . For a refresher, see LXF292,
Network programming
TCP/IP is a collection of protocols and services used for running the internet. TCP stands for transmission control protocol and IP stands for internet protocol. There are public documents called Request For Comments (RFCs) that describe each TCP/IP protocol and service in more detail using technical terms. Learn more about RFCs at www.ietf.org/standards/rfcs.
Rust offers the necessary data structures, functions and methods for supporting the development of TCP/IP servers and clients. As an example, before being able to accept TCP client connections, the server code needs to use the TcpListener::bind() function for binding to the desired connection details. After that, the program can begin accepting incoming connections. In most cases incoming connections are processed using for loops. You can learn more about the networking primitives of Rust at https://doc.rust-lang.org/std/net.
Generally speaking, developing UDP servers is much simpler than developing TCP servers because UDP doesn’t keep information about the state of a connection. As a result, UDP connections open and close all the time, whereas TCP connections are active until they’re closed for some reason. TCP/IP clients are easier to implement than TCP/IP servers.
A simple server
First, we’re going to develop a simple TCP server that implements the Echo service, which is saved as echo_ server.rs. The important.part of echo_server.rsis let listener = TcpListener::bind(my_bind_final). unwrap(); for stream in listener.incoming() { match stream { Err(e) => { println!("Failed: {}”, e) }
The main functkon of the Rust implementation for a concurrent TCP server that implements the Echo service.
Ok(stream) => { thread::spawn(move || { handle_ request(stream)}); }
}
}
The previous code is part of the main() function and is used for handling incoming client connections. As is the case with TCP servers, we need to bind the server to the desired hostname or IP address and port number combination using TcpListener::bind() and then start waiting for incoming client connections, which in this case is done with the listener.incoming() call. That call returns the data required for establishing a connection with each client. When the TCP server accepts a new connection from a TCP client, it processes that client connection with the handle_request() function.