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"] }
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.
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;
...
}
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, let’s 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.
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
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 by one of them.
The source code is here.
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