Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Erlang: Finding my IP Address

Tags:

erlang

I'm attempting to complete a Load Balancer / Login Server / Game Server setup using Redis for some parts. Load balancing is one of them. In my Redis load balancing instance I'm using ordered sets. The key is the application name, the members are the IP addresses of the game servers.

Herein lies my issue. I would like to use a public method within erlang. I cannot find anything that fits my needs. I'm wondering if I'm over looking something.

{ok, L} = inet:getif(),
IP = element(1, hd(L)),

Gives me what I'm looking for. I believe currently it's {192,168,0,14}. But the function is not "public."

{ok, Socket} = gen_tcp:listen(?PORT_LISTEN_GAME, [{active,once}, {reuseaddr, true}]),
{ok, {IP, _} = inet:sockname(Socket),

Gives me {0,0,0,0}. I've tried inet:getaddr("owl") which gives me {127,0,1,1}.

Am I limited to sending messages via TCP and using inet:peername(Socket)? Seems like a lot to get something so simple. All the different parts of my app are running on the same computer for testing. Is it going to give me back {127,0,0,1}? That wouldn't work. I need to send the IP back to the user (my mobile phone) so they can link up with the proper server. Loopback wouldn't do....

Current Code

I would like to thank all the responses. Yes, I noticed Lol4t0's comment just after the New Year. So I changed my code to reflect that. Posting this for the slow people like myself. I have to wrack my brain for a bit to get these things to click.

hd([Addr || {_, Opts} <- Addrs,
    {addr, Addr} <- Opts,
    {flags, Flags} <- Opts,
    lists:member(loopback,Flags) =/= true]).
like image 467
Nolan Robidoux Avatar asked Oct 07 '15 05:10

Nolan Robidoux


2 Answers

We've been successfully using this function to get the first non-local IPv4 address:

local_ip_v4() ->
    {ok, Addrs} = inet:getifaddrs(),
    hd([
         Addr || {_, Opts} <- Addrs, {addr, Addr} <- Opts,
         size(Addr) == 4, Addr =/= {127,0,0,1}
    ]).

It can of course be changed to return IPv6 as well if that is what you want.

like image 60
Adam Lindberg Avatar answered Sep 19 '22 22:09

Adam Lindberg


You should first understand that your host can have more than one unique IP address. In fact all {0,0,0,0}, {127,0,0,1} (hey! actually all 127.0.0.0/8 is your addresses) and {192,168,0,14} are all your valid IP addresses. Additionally if your host will have some other interfaces connected you'll get even more IP addresses. So you basically can't find a function that will get your the IP address you need.

Instead it is a well documented function in the inet module that will list interfaces each with its own IP address:

getifaddrs() -> {ok, Iflist} | {error, posix()}

Types:

Iflist = [{Ifname, [Ifopt]}]
Ifname = string()
Ifopt = {flag, [Flag]}
      | {addr, Addr}
      | {netmask, Netmask}
      | {broadaddr, Broadaddr}
      | {dstaddr, Dstaddr}
      | {hwaddr, Hwaddr}
Flag = up
     | broadcast
     | loopback
     | pointtopoint
     | running
     | multicast
Addr = Netmask = Broadaddr = Dstaddr = ip_address()
Hwaddr = [byte()]
like image 28
Lol4t0 Avatar answered Sep 21 '22 22:09

Lol4t0