Erlang:查找我的 IP 地址

Erlang: Finding my IP Address

我正在尝试使用 Redis 完成负载平衡器/登录服务器/游戏服务器的某些部分设置。负载均衡就是其中之一。在我的 Redis 负载平衡实例中,我使用的是有序集。 key是应用名称,member是游戏服务器的IP地址。

这就是我的问题。我想在 erlang 中使用 public 方法。我找不到任何适合我需要的东西。我在想我是不是看多了。

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

给了我正在寻找的东西。我相信目前它是{192,168,0,14}。但是函数不是"public."

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

给我 {0,0,0,0}。我试过 inet:getaddr("owl") ,它给了我 {127,0,1,1}.

我是否仅限于通过 TCP 发送消息并使用 inet:peername(Socket)?获得如此简单的东西似乎很多。我的应用程序的所有不同部分都 运行 在同一台计算机上进行测试。它会把 {127,0,0,1} 还给我吗?那是行不通的。我需要将 IP 发送回用户(我的手机 phone),这样他们就可以 link 使用正确的服务器。环回不行....

当前代码

感谢所有回复。是的,我注意到 Lol4t0 的评论刚过完年。所以我改变了我的代码来反映这一点。为像我这样慢的人发布这个。我必须绞尽脑汁才能让这些东西点击。

hd([Addr || {_, Opts} <- Addrs,
    {addr, Addr} <- Opts,
    {flags, Flags} <- Opts,
    lists:member(loopback,Flags) =/= true]).

您应该首先了解您的主机可以拥有多个唯一的 IP 地址。实际上所有 {0,0,0,0}{127,0,0,1}(嘿!实际上所有 127.0.0.0/8 都是您的地址)和 {192,168,0,14} 都是您的有效 IP 地址。此外,如果您的主机将连接一些其他接口,您将获得更多的 IP 地址。因此,您基本上找不到可以获取所需 IP 地址的函数。

相反,functioninet 模块中有详细记录,它将列出每个接口都有自己的 IP 地址:

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()]

我们已成功使用此函数获取第一个非本地 IPv4 地址:

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

当然也可以更改为 return IPv6,如果需要的话。

使用 OTP 中的 getifaddr() 函数可提供机器可用的所有接口的详细列表。以下解决方案应该会清除很多困惑的 erlang 新手,因为它也难倒了我。此功能未优化但可读性很强,并为您的机器提供本地 IP4 地址,就像您在 LAN 聚会上使用的那样:

 %Get the local IP4 address of this machine in the local network (LAN party address)
local_ip_v4() ->
  {ok, IntfList} = inet:getifaddrs(), %Get a list of all interfaces (Wifi, Lan, Internal loopback etc)

  %Filter this list to look for an interface that is "up and running" (has a connection) 
   SelectedInf = lists:foldl( fun(El, SelectedIf)->
                {InfName,InfOpts} = El,
                Flags = lists:keyfind(flags,1,InfOpts),
                case Flags of
                  {flags,[up,running]} ->
                    {InfName,InfOpts};
                  _->
                    SelectedIf
                end
                end,
                none,IntfList),

  io:format("~n INTERFACES: ~p ",[IntfList]),
  io:format("~n Selected INTERFACE: ~p ",[SelectedInf]),

  %Look through this interface's properties for the addresses, but only match one
  % that has 4 components in the tuple!
  {Sel_InfName,Sel_InfOpts} = SelectedInf,
  Address_I4 = lists:foldl( fun(El,Addr)->
                              case El of
                                {addr,{A,B,C,D}}->
                                  {A,B,C,D};
                                _->
                                  Addr
                              end
                            end, none, Sel_InfOpts),
  io:format("~n Selected INTERFACE IP4: ~p ~n",[Address_I4]),
  Address_I4.

希望这对您有所帮助:)