Rustで適当な空いているポートを取得したいことがあり、以下のように書いたらポート番号が取れて便利でした。
use std::io;
use std::net::TcpListener;
fn available_port() -> io::Result<u16> {
match TcpListener::bind("localhost:0") {
Ok(listener) => {
listener.local_addr().unwrap().port()
}
Err(e) => Err(e)
}
}
fn main() {
println!("port: {}", available_port().unwrap());
}
TcpListener::bind
の引数に localhost:0
を渡すと、OSが空いているポートへの割り当てを要求するらしいので、それを使ってbindしてポート番号を取得してからそのリスナーをcloseすればそのポートが空くので空きポートが取れる、という寸法です。
実行する度に異なるポートが割り当てられています。
$ cargo run
Running `target/debug/sample`
port: 59103
$ cargo run
Running `target/debug/sample`
port: 62786
$ cargo run
Running `target/debug/sample`
port: 62799
Hyperを使う場合は、Hyperは内部でTcpListenerを使っているので localhost:0
を指定すれば同じように適当なポートでbindされます。
Server::http(hello).listen("localhost:0").unwrap();