1 Introduction
1.1 Overview
std.lib.network is part of the standard foundation library set. This page collects the public API reference for the namespace.
2 Walkthrough
2.1 Local host information
std.lib.network returns information about the local machine: host address, IP, and hostname.
query local host details
^{:refer std.lib.network/local-host :added "3.0"}
(local-host)
=> java.net.Inet4Address
^{:refer std.lib.network/local-ip :added "3.0"}
(local-ip)
=> string?
^{:refer std.lib.network/local-hostname :added "3.0"}
(local-hostname)
=> string?
2.2 Port availability
port:check-available, port:get-available, and wait-for-port help allocate and synchronise ports.
check and find available ports
^{:refer std.lib.network/port:check-available :added "4.0"}
(port:check-available 51311)
=> anything
^{:refer std.lib.network/port:get-available :added "4.0"}
(port:get-available [51312 51313])
=> number?
3 API
- ip-score
- local-host
- local-hostname
- local-ip
- local-ip-lan
- local-shortname
- port:check-available
- port:get-available
- socket
- socket:address
- socket:local-address
- socket:local-port
- socket:port
- wait-for-port
NONE
(defn- ip-score
[^String ip]
(cond (clojure.string/starts-with? ip "192.168.") 0
(clojure.string/starts-with? ip "10.") 1
(and (clojure.string/starts-with? ip "172.")
(let [n (try (Integer/parseInt (second (clojure.string/split ip #"\.") 0))
(catch Throwable _ 0))]
(<= 16 n 31))) 2
:else 3))
link
v 3.0
(defn ^java.net.Inet4Address local-host
([]
(java.net.InetAddress/getLocalHost)))
link
(local-host) ;; #object[java.net.Inet4Address 0x4523dee "chapterhouse.base.local/127.0.0.1"] => java.net.Inet4Address
v 3.0
(defn local-hostname
([]
(.getHostName (local-host))))
link
(local-hostname) ;; "chapterhouse.base.local" => string?
v 4.0
(defn local-ip-lan
[]
(->> (NetworkInterface/getNetworkInterfaces)
(enumeration-seq)
(filter (fn [^NetworkInterface ni]
(and (.isUp ni)
(not (.isLoopback ni))
(not (.isPointToPoint ni)))))
(mapcat (fn [^NetworkInterface ni]
(enumeration-seq (.getInetAddresses ni))))
(filter (fn [^InetAddress addr]
(and (instance? java.net.Inet4Address addr)
(not (.isLoopbackAddress addr))
(not (.isLinkLocalAddress addr)))))
(map #(.getHostAddress ^InetAddress %))
(sort-by ip-score)
first))
link
(local-ip-lan) => (any nil? string?)
v 3.0
(defn local-shortname
([]
(-> (local-hostname)
(clojure.string/split #"\.")
first)))
link
(local-shortname) ;; "chapterhouse" => string?
v 4.0
(defn port:check-available
([port]
(try
(with-open [^ServerSocket s (ServerSocket. port)]
(.setReuseAddress s true)
(.getLocalPort s))
(catch Throwable t
false))))
link
(port:check-available 51311) => anything
v 4.0
(defn port:get-available
([ports]
(reduce (fn [_ i]
(if (port:check-available i) (reduced i)))
nil ports)))
link
(port:get-available [51312 51313]) => number?
v 3.0
(defn ^Socket socket
([^long port]
(socket nil port))
([^String host ^long port]
(Socket. (or host "localhost") port)))
link
(h/suppress (with-open [s ^java.net.Socket (socket 51311)] s)) => (any nil? java.net.Socket)
v 3.0
(defn socket:address
([^Socket socket]
(str (.getInetAddress socket))))
link
(with-open [s (java.net.ServerSocket. 0)] (with-open [c (socket (.getLocalPort s))] (socket:address c))) => "localhost/127.0.0.1"
v 3.0
(defn socket:local-address
([^Socket socket]
(str (.getLocalAddress socket))))
link
(with-open [s (java.net.ServerSocket. 0)] (with-open [c (socket (.getLocalPort s))] (socket:local-address c))) => "/127.0.0.1"
v 3.0
(defn socket:local-port
([^Socket socket]
(.getLocalPort socket)))
link
(with-open [s (java.net.ServerSocket. 0)] (with-open [c (socket (.getLocalPort s))] (socket:local-port c))) => number?
v 3.0
(defn socket:port
([^Socket socket]
(.getPort socket)))
link
(with-open [s (java.net.ServerSocket. 0)] (with-open [c (socket (.getLocalPort s))] (socket:port c))) => number?
wait-for-port ^
[host port] [host port {:keys [timeout pause], :as opts}]
waits for a port to be ready
v 3.0
(defn wait-for-port
([host port]
(wait-for-port host port {}))
([host port {:keys [timeout pause] :as opts}]
(let [t0 (time/time-ms)]
(loop [retries 0]
(let [[retry? timeout?]
(try (env/close (socket host port))
[false false]
(catch ConnectException _
(if (or (nil? timeout)
(< (time/elapsed-ms t0) timeout))
[true false]
[false true])))]
(cond retry?
(do (Thread/sleep (long (or pause 100)))
(recur (inc retries)))
:else
(let [data {:host host
:port port
:elapsed (time/elapsed-ms t0)
:retries retries}]
(if timeout?
(throw (ex-info "Timed out" data))
data))))))))
link
(wait-for-port "localhost" 51313 {:timeout 1000}) => (throws)
4 std.lib.network: A Comprehensive Summary
The std.lib.network namespace provides a collection of utility functions for network-related operations in Clojure, primarily focusing on local host information, socket management, and port availability checks. It leverages Java's java.net package to offer convenient wrappers for common networking tasks.
Key Features and Concepts:
- Local Host Information:n
local-host: Returns thejava.net.Inet4Addressobject representing the local host.nlocal-ip: Retrieves the IP address of the local host as a string.nlocal-hostname: Returns the full hostname of the local machine.nlocal-shortname: Extracts the short name (first part) of the local hostname.nn2. Socket Management:nsocket: Creates a newjava.net.Socketobject, allowing connection to a specified host and port.nsocket:port: Gets the remote port number of a connected socket.nsocket:local-port: Gets the local port number of a connected socket.nsocket:address: Returns the remote IP address of a connected socket.nsocket:local-address: Returns the local IP address of a connected socket.nn3. Port Availability and Waiting:nport:check-available: Checks if a given port is available for use by attempting to bind aServerSocketto it.nport:get-available: Finds the first available port from a provided list of ports.nwait-for-port: Blocks execution until a specified port on a given host becomes available, with configurable timeout and pause intervals. This is useful for synchronizing services during startup or testing.nn4. Component Protocol Integration:n * Thejava.net.Socketclass is extended to implement thestd.protocol.component/IComponentandstd.protocol.component/IComponentQueryprotocols. This allowsSocketobjects to be managed as components within thefoundation-baseecosystem, enabling standardized lifecycle management (-start,-stop,-kill) and status querying (-started?,-stopped?,-remote?).
Usage and Importance:
std.lib.network is a vital module for any application within the foundation-base project that needs to interact with network resources. It simplifies common networking tasks, from identifying local machine details to managing socket connections and ensuring port availability. The integration with the std.protocol.component allows network resources to be treated as first-class components, promoting a consistent and manageable approach to resource lifecycle within the larger system.