Wednesday, January 19, 2011

Detect your host IP with Clojure

Recently I was faced with trivial task of detecting a host's IP address where the host could have multiple network interfaces. Based on how the local network was configured, you might have a luck with just a one liner in Clojure:

(import (java.net InetAddress))
(println (InetAddress/getLocalHost))

This will produce following:
;;user=> (import (java.net InetAddress))
;;(println (InetAddress/getLocalHost))
;;user=>
;;inet4address kpad/127.0.0.1
;;nil

Obviosly, that is not what you might be looking for since it is just a loopback address.
To find the your host LAN IP address, you need to find the not loopback interface and obtain the IP that is bound to it. It turns out it is pretty easy in Clojure. Here is whole thing:
===================================================================
import (java.net NetworkInterface))
(def ip
     (let [ifc (NetworkInterface/getNetworkInterfaces)
    ifsq (enumeration-seq ifc)
    ifmp (map #(bean %) ifsq)
    ipsq (filter #(false? (% :loopback)) ifmp)
    ipa (map :interfaceAddresses ipsq)
    ipaf (nth ipa 0)
    ipafs (.split (str ipaf) " " )
    ips (first (nnext ipafs))]
       (str (second (.split ips "/")))))
 

========================================================================

This will produce following:
;;user=> (println ip)
;;192.168.1.70
;;nil

Note: I am still learning Clojure and surely there will be better way of doing this. If you happen to know, please share. Thanks for reading.

3 comments:

  1. I would write your example like this:

    (defn local-addresses []
    (->> (java.net.NetworkInterface/getNetworkInterfaces)
    enumeration-seq
    (map bean)
    (filter (complement :loopback))
    (mapcat :interfaceAddresses)
    (map #(.. % (getAddress) (getHostAddress))))

    then use (first (local-addresses)) to get the IP.

    But the following simple alternative seems to have the same effect:

    (.getHostAddress (java.net.InetAddress/getLocalHost))

    ReplyDelete
  2. To clarify, (java.net.InetAddress/getLocalHost) gives *me* the same result as the longer code. It doesn't return a loopback address for me, so it's presumably platform-dependent somehow.

    ReplyDelete
  3. Thanks for your version, Steve. (java.net.InetAddress/getLocalHost) return value depends on the LAN config of your host. The longer code can give you the active IP that your host is using. I liked your version of the code. Thanks for sharing.

    ReplyDelete

Sociable