【问题标题】:Erlang: Finding my IP AddressErlang:查找我的 IP 地址
【发布时间】:2016-01-04 05:05:04
【问题描述】:

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

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

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

给我我正在寻找的东西。我相信目前是 {192,168,0,14}。但该功能不是“公开的”。

{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 发回给用户(我的手机),以便他们可以连接到正确的服务器。 Loopback 不行....

当前代码

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

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

【问题讨论】:

    标签: erlang


    【解决方案1】:

    使用 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.
    

    希望这会有所帮助:)

    【讨论】:

      【解决方案2】:

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

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

      如果你想要的话,当然也可以将其更改为返回 IPv6。

      【讨论】:

      • 我正在研究 proplists,但这是首选。我不太熟悉以这种方式构建列表。谢谢你。我稍微修改了一下。也许你会更喜欢这个。 :) 发生在我身上的是它正在抓取下一个(ipv6)环回......虽然如果我使用你的大小限制它就不会发生。
      • hd([Addr || {IF, Opts}
      • @NolanRobidoux 这可以随机给你 IPv4 和 IPv6 并且它不考虑名称为 lo0 等的接口。
      • 我想无论如何使用它总会有一些调整。对我来说,只要我的手机可以与我的电脑通话,我就获得 IPv4 或 IPv6。 :)
      • @NolanRobidoux,“发生在我身上的是它正在抓取下一个 (ipv6) 环回”您只需要检查 flags 而不是应用 hack。
      【解决方案3】:

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

      相反,它是inet 模块中的一个有据可查的function,它将列出每个接口都有自己的 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()]
      

      【讨论】:

      • 谢谢。应该一直在在线 erlang 手册页上的列表中。我知道每个接口都有一个 IP :) 我只需要一个唯一的有效接口(即不是任何环回),这样我的手机就可以与之通信,并且游戏服务器实例可以适当地进行速率限制。这符合要求。
      猜你喜欢
      • 2016-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-15
      • 2012-11-17
      • 2012-09-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多