Erlang:查找我的IP地址

vuktfyat  于 2022-12-08  发布在  Erlang
关注(0)|答案(3)|浏览(216)

我正在尝试用Redis完成一个负载平衡器/登录服务器/游戏服务器的安装。负载平衡就是其中之一。在我的Redis负载平衡示例中,我使用的是有序集。关键是应用程序名,成员是游戏服务器的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发送回用户(我移动的),这样他们才能连接到正确的服务器。环回不行......

当前代码

我想感谢所有的回复。是的,新年刚过我就注意到了Lol 4 t0的评论。所以我修改了代码来反映这一点。为像我这样慢的人发布这篇文章。我必须绞尽脑汁才能让这些东西点击。

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

eyh26e7m1#

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

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

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

nnvyjq4y

nnvyjq4y2#

你应该首先了解你的主机可以有多个唯一的IP地址。事实上所有的{0,0,0,0}{127,0,0,1}(嘿!实际上所有的127.0.0.0/8都是你的地址)和{192,168,0,14}都是你的有效IP地址。另外,如果你的主机有一些其他接口连接,你会得到更多的IP地址。所以你基本上找不到一个函数,将获得你的 * 您需要的 * IP地址。
相反,它是inet模块中的一个详细说明的函数,该函数将列出每个接口及其各自的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()]
z18hc3ub

z18hc3ub3#

使用OTP中的getifaddr()函数给出了机器可用的所有接口的详细列表。下面的解决方案应该可以解决很多Erlang新手的困惑,因为它也难倒了我。这个函数没有优化,但可读性很强,它给你的机器提供了本地IP4地址,就像你在局域网聚会上使用的一样:

%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.

希望这对你有帮助:)

相关问题