DEV Community

Carlos Armando Marcano Vargas
Carlos Armando Marcano Vargas

Posted on • Originally published at carlosmv.hashnode.dev on

How To Build a CLI Tool To Show Ports Available | Rust

Sometimes, when I'm writing a web application or installing one, I find that is not possible to start it up because the port that is supposed to use is used by other applications.

So, that is the reason I want to create a program that shows me if a port I want to use is available.

This CLI tool is going to have the following features:

  • Show if a specific port is available

  • Read multiple port numbers from the console and return which ones are available.

Requirements

  • Rust installed

For this project, we are going to use the Clap crate for parsing the command line arguments.

cargo.toml

[dependencies]

clap = { version = "4.4.6", features = ["derive"] }

Enter fullscreen mode Exit fullscreen mode

main.rs

First, we are going to create a program that checks a specific port and returns if the port is available or not.


use std::net::TcpListener;

fn main() {
    let port = 3000;

    let is_available = port_is_available(port);

    if is_available {
        println!("Port: {} is available", port);
    } else {
        println!("Port: {} is NOT available", port)
    }
}

fn port_is_available(port: u16) -> bool {
    match TcpListener::bind(("127.0.0.1", port)) {
        Ok(_) => true,
        Err(_) => false,
    }
}

Enter fullscreen mode Exit fullscreen mode

In the code above, we create the port_is_available function that has port as a parameter and creates a TCP listener to the address passed using the TcpListener::bind() function. The port_is_available function returns true if the TCP listener is ready for connection, and false, otherwise.

In the main function, we declare a variable to store the port we want to check.

Then, we create the is_available variable to store the return value when we call the port_is_available function.

We create a control flow, to print if a port is available or not.

Next, we run the cargo run command in our console.

The image above shows in the console the output of the program when trying to connect to a port that has been used.

Now, instead of having to declare a variable with the port number and run the program, let's add Clap to pass the port number as an argument using the console.

use clap::Parser;

#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {

    #[arg(short, long)]
    Port: u16,
}

fn main() {
    let args = Args::parse();
    let port = args.Port;
...

}

Enter fullscreen mode Exit fullscreen mode

We compile the program and go to the executable file, I have it this path: target/debug/port-searcher.

Run the following command in our console:

port-searcher --port 8000

Enter fullscreen mode Exit fullscreen mode

So far, we have implemented the first feature of our CLI tool.

Now, lets add the feature that allows the program to show multiple ports available.

use std::net::TcpListener;

...

fn main() {
   ...    
    let list_of_ports = [3000, 4000, 8000, 8080, 9000, 5000, 9090];
    ports_available(list_of_ports.to_vec());
...
}

fn ports_available(ports: Vec<u16>) {
    for port in ports {
        if port_is_available(port) {
            println!("port {} is available", port);
        } else {
            println!("Port: {} is NOT available", port)
        }
    }
}
...

Enter fullscreen mode Exit fullscreen mode

In the code above, we create a vector with multiple ports. Then, the program iterates through the vector and creates a connection with every port in the list. Showing which one is available.

Now, let's modify the Args struct so our CLI tool can read multiple port numbers from our console.

#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {

    #[arg(num_args(0..), short, long)]
    ports: Vec<u16>,

}

fn main() {
    let args = Args::parse();
    let ports = args.ports;

    ports_available(ports.to_vec())

}

Enter fullscreen mode Exit fullscreen mode

We changed the attribute port for ports and the type is a vector of u16 integers.

We run the following command in our console:

port-searcher --ports 4000 3000 5000 9000 8080 9090 5174

Enter fullscreen mode Exit fullscreen mode

Conclusion

In this article, we learn how to check if a port is available, how to use Clap to pass arguments from the command line, and how to check multiple ports.

This is useful when we have multiple services running and we don't know if a port is been used for one of them.

Thank you for taking the time to read this article.

If you have any recommendations about other packages, architectures, how to improve my code, my English, or anything; please leave a comment or contact me through Twitter, or LinkedIn.

Resources

How to find an available TCP port in Rust

A fast port scanner in 100 lines of Rust

Clap Documentation

Top comments (0)