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 地址的函数。
相反,function 在 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()]
我们已成功使用此函数获取第一个非本地 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.
希望这对您有所帮助:)
我正在尝试使用 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 地址的函数。
相反,function 在 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()]
我们已成功使用此函数获取第一个非本地 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.
希望这对您有所帮助:)