TCP

Rust

Socket address type

Client

A client connects to a service using TcpStream::connect() where the service is specified as host:port. It can then read and write bytes to the returned stream. The client is /EchoClient.rs:


use std::io::{self, Read, Write, BufRead};
use std::net::TcpStream;
use std::env;
use std::str;
use std::io::stdout;

fn main() -> std::io::Result<()> {

    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        println!("Usage {} hostname", args[0]);
        std::process::exit(1);
    }
    let hostname = &args[1];

    let mut stream = TcpStream::connect(hostname.to_string() + &":2000")
	.expect("Couldn't connect to the server...");

    // from https://stackoverflow.com/questions/30186037/how-can-i-read-a-single-line-from-stdin
    print!("Enter line:"); stdout().flush();
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
	let line = line.unwrap();
	println!("Read line: '{}'", line);
	if &line == "BYE" {
	    break;
	}

	stream.write(line.as_bytes())
	    .expect("Error on write");

	let mut echo_bytes: [u8; 2048] = [0; 2048];
	stream.read(&mut echo_bytes[..])
	    .expect("Error on read");

	let echo = str::from_utf8(&echo_bytes).unwrap();
	println!("Echoed: '{}'", echo);
	print!("Enter line:"); stdout().flush();
    }
    Ok(())
} // the stream is closed here

Multi-threaded Server

The server binds to ANY host and listens by TcpListener::bind(). It accepts a connection using incoming and can then read and write from the resultant stream. If the server wants to listen to IPv4 only, then the ANY host is "0.0.0.0". If it is running a dual IPv4/IPv6 stack, then the ANY host should be "::" (enclosed as "[::}" to avoid confusion with the ':' in "host:port") for both IPv4 and IPv6. The program is /EchoServer.rs:


// From https://gist.github.com/fortruce/828bcc3499eb291e7e17

use std::net::{TcpListener, TcpStream};
use std::thread;
use std::io::Read;
use std::io::Write;

fn handle_client(mut stream: TcpStream) {
    println!("Connected");
    // read 2048 bytes at a time from stream echoing back to stream
    loop {
        let mut read = [0; 2048];
        match stream.read(&mut read) {
            Ok(n) => {
                if n == 0 { 
                    // connection was closed
                    break;
                }
                stream.write(&read[0..n]).unwrap();
            }
            Err(_err) => {
                //panic!(err);
		break;
            }
        }
    }
    println!("Disconnected");
}

fn main() {
    //let listener = TcpListener::bind("0.0.0.0:2000").unwrap();
    let listener = TcpListener::bind("[::]:2000").unwrap();

    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                thread::spawn(move || {
                    handle_client(stream);
                });
            }
            Err(_) => {
                println!("Error");
            }
        }
    }
}

Socket options


Copyright © Jan Newmarch, jan@newmarch.name
Creative Commons License
" Network Programming using Java, Go, Python, Rust, JavaScript and Julia" by Jan Newmarch is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License .
Based on a work at https://jan.newmarch.name/NetworkProgramming/ .

If you like this book, please contribute using PayPal