port_rs/
lib.rs

1pub use self::local::get_free_port;
2
3pub mod local {
4
5    use rand::{self, Rng};
6    use std::io::ErrorKind;
7    use std::net::TcpStream;
8    /// Get Local Free Port.
9    ///
10    /// # Examples
11    ///
12    /// ```
13    /// use port_rs::get_free_port;
14    /// use port_rs::check_free;
15    ///
16    /// let arg = get_free_port();
17    ///
18    /// assert_eq!(check_free(arg), true);
19    /// ```
20    pub fn get_free_port() -> u16 {
21        get_free_range_port(5000, 49151)
22    }
23
24    pub fn get_free_range_port(start_port: u16, end_port: u16) -> u16 {
25        let mut rng = rand::thread_rng();
26
27        let r = loop {
28            let port = rng.gen_range(start_port..end_port);
29            if check_free(port) {
30                break port;
31            }
32        };
33
34        r
35    }
36
37    // 校验端口是否可用
38    pub fn check_free(port: u16) -> bool {
39        let mut ip_addr = String::from("127.0.0.1:");
40        ip_addr.push_str(&port.to_string());
41        let con = TcpStream::connect(&ip_addr);
42
43        match con {
44            Ok(_) => {
45                println!("端口被占用{}!", ip_addr);
46                return false;
47            }
48            Err(err) => {
49                if err.kind() == ErrorKind::ConnectionRefused {
50                    return true;
51                } else {
52                    println!("校验端口{}发生错误:{}", ip_addr, err);
53                    return false;
54                }
55            }
56        };
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use crate::local::{check_free, get_free_port};
63    #[test]
64    fn get_free_test() {
65        for _ in 0..100 {
66            assert_eq!(check_free(get_free_port()), true);
67        }
68    }
69}