How To Build a CLI Tool To Show Ports Available | Rust
Tags: rust, ports
Published: 2023-10-24 04:10:18

---
title: How To Build a CLI Tool To Show Ports Available | Rust
published: true
date: 2023-10-16 13:02:44 UTC
tags: #rust #ports
canonical_url: https://carlosmv.hashnode.dev/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](https://docs.rs/clap/latest/clap/) crate for parsing the command line arguments.

cargo.toml

```
[dependencies]

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

```

**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,
    }
}

```

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.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1696709887949/836e0c02-929d-497b-bdbf-1ed3745a3375.png)

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1696709941026/362f0dcf-c5a3-49a6-8ed2-f84bbde61006.png)

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;
...

}

```

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

```

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)
        }
    }
}
...

```

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.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1696721609561/7a9c3ae6-156f-4fb2-bb75-4e85343dc21c.png)

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())

}

```

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

```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1696725641762/45c7f1c6-7006-42e6-b61d-8c0d70c9b3bf.png)

### 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**](https://twitter.com/Carlos_marcv), or [**LinkedIn**](https://www.linkedin.com/in/carlos-marcano-a2135a134/).

### Resources

[How to find an available TCP port in Rust](https://elliotekj.com/posts/2017/07/25/find-available-tcp-port-rust/)

[A fast port scanner in 100 lines of Rust](https://kerkour.com/rust-fast-port-scanner)

[Clap Documentation](https://docs.rs/clap/latest/clap/)