Echo server

Rust has a minimal UDP package in std::net::UdpSocket. This is good enough for basic use. It uses the functions recv_from() and send_to() to read and write from a UDP socket. The socket is bound to for UDP4 only or [::]:2000 for dual stack UDP4 or UDP6.

The project is created by cargo new echoserver and built and run from within the directory echoserver The file src/main.rs should contain EchoServer.rs:

//use std::io::{self, Read, Write, BufRead};
use std::net::UdpSocket;
//use std::env;
//use std::str;

fn main() -> std::io::Result<()> {
    //let socket = UdpSocket::bind("")?; // for UDP4
    let socket = UdpSocket::bind("[::]:2000")?;  // for UDP4/6
    let mut buf = [0; 2048];

    loop {
        // Receives a single datagram message on the socket.
	// If `buf` is too small to hold
        // the message, it will be cut off.
        let (amt, src) = socket.recv_from(&mut buf)?;

        // Redeclare `buf` as slice of the received data
	// and send data back to origin.
        let buf = &mut buf[..amt];
        socket.send_to(buf, &src)?;

Echo client

The EchoClient is similar to the TCP case, except for the actual communication (of course!). One pecularity of the Rust implementation of UDP is the requirement to bind the client to an address/port. Even in C, you don't have to do that! I've chosen to use the wildcard address :: and the zero port to lead to an ephemeral port as [::]:0. Apart from that, it uses send_to() and recv_from() as in the server.

The code is EchoClient.rs:

use std::io::{self, BufRead};
use std::net::UdpSocket;
use std::env;
use std::str;

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

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

    let socket = UdpSocket::bind("[::]:0")?;  // for UDP4/6
    //socket.connect(hostname.to_string() + &":2000").expect("couldn't connect to address");

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

	socket.send_to(line.as_bytes(), hostname.to_string() + &":2000")
	    .expect("Error on send");

	let mut buf = [0; 2048];
	let (amt, _src) = socket.recv_from(&mut buf)?;

	let echo = str::from_utf8(&buf[..amt]).unwrap();
	println!("Echo {}", echo);

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