0
我需要获取iOS设备的IP地址。 GStack.GetLocalAddressList返回所有地址,包括Cellular接口的地址。 如何获得与wifi接口(en0)相关的地址?iOS设备的IP地址
@widi 如果类似的问题被要求在不同的语言平台,但这并不意味着不存在为我指定了一个答案 - 读取标签 - 它说:“德尔福”“firemonkey ”。这就像在C#中问一个问题,并欣喜地获得COBOL中的代码示例。
我需要获取iOS设备的IP地址。 GStack.GetLocalAddressList返回所有地址,包括Cellular接口的地址。 如何获得与wifi接口(en0)相关的地址?iOS设备的IP地址
@widi 如果类似的问题被要求在不同的语言平台,但这并不意味着不存在为我指定了一个答案 - 读取标签 - 它说:“德尔福”“firemonkey ”。这就像在C#中问一个问题,并欣喜地获得COBOL中的代码示例。
你必须实现自己的IP地址枚举,该枚举也返回适配器信息。这里有一个例子:
uses IPAddressHelper, IdStack, IdGlobal;
procedure TForm2.Button1Click(Sender: TObject);
var
LocalIPs: TIdStackLocalAddressList;
I: Integer;
begin
Memo1.Lines.Clear;
TIdStack.IncUsage;
try
LocalIPs := TIdStackLocalAddressList.Create;
try
GStack.GetLocalAddressList(LocalIPs);
for I := 0 to LocalIPs.Count - 1 do
begin
if LocalIPs[I] is TIdStackLocalAddressIPv4Ex then
Memo1.Lines.Add(TIdStackLocalAddressIPv4Ex(LocalIPs[I]).IfaName + LocalIPs[I].IPAddress + ' ' + BoolToStr(TIdStackLocalAddressIPv4Ex(LocalIPs[I]).IsWifi, True));
end;
finally
LocalIPs.Free;
end;
finally
TIdStack.DecUsage;
end;
end;
该单元实现了先进的Stack类,包括适配器名称和一些功能来帮助决定一个网络是蜂窝或无线网络连接。
unit IPAddressHelper;
interface
uses
Classes,
IdStack,
IdStackConsts,
IdGlobal,
IdStackBSDBase,
IdStackVCLPosix;
type
TIdStackLocalAddressIPv4Ex = class(TIdStackLocalAddressIPv4)
protected
FFlags: Cardinal;
FIfaName: string;
public
function IsWifi: Boolean;
function IsPPP: Boolean;
property IfaName: string read FIfaName;
constructor Create(ACollection: TCollection; const AIPAddress, ASubNetMask: string; AName: MarshaledAString; AFlags: Cardinal); reintroduce;
end;
TIdStackLocalAddressIPv6Ex = class(TIdStackLocalAddressIPv6)
protected
FFlags: Cardinal;
FIfaName: string;
public
function IsWifi: Boolean;
function IsPPP: Boolean;
property IfaName: string read FIfaName;
constructor Create(ACollection: TCollection; const AIPAddress: string; AName: MarshaledAString; AFlags: Cardinal); reintroduce;
end;
TIdStackVCLPosixEx = class(TIdStackVCLPosix)
public
procedure GetLocalAddressList(AAddresses: TIdStackLocalAddressList); override;
end;
implementation
uses
Posix.Base,
Posix.NetIf,
Posix.NetinetIn,
SysUtils;
function getifaddrs(ifap: pifaddrs): Integer; cdecl; external libc name _PU + 'getifaddrs'; {do not localize}
procedure freeifaddrs(ifap: pifaddrs); cdecl; external libc name _PU + 'freeifaddrs'; {do not localize}
procedure TIdStackVCLPosixEx.GetLocalAddressList(AAddresses: TIdStackLocalAddressList);
var
LAddrList, LAddrInfo: pifaddrs;
LSubNetStr: String;
begin
if getifaddrs(@LAddrList) = 0 then
try
AAddresses.BeginUpdate;
try
LAddrInfo := LAddrList;
repeat
if (LAddrInfo^.ifa_addr <> nil) and ((LAddrInfo^.ifa_flags and IFF_LOOPBACK) = 0) then
begin
case LAddrInfo^.ifa_addr^.sa_family of
Id_PF_INET4: begin
if LAddrInfo^.ifa_netmask <> nil then begin
LSubNetStr := TranslateTInAddrToString(PSockAddr_In(LAddrInfo^.ifa_netmask)^.sin_addr, Id_IPv4);
end else begin
LSubNetStr := '';
end;
TIdStackLocalAddressIPv4Ex.Create(AAddresses, TranslateTInAddrToString(PSockAddr_In(LAddrInfo^.ifa_addr)^.sin_addr, Id_IPv4), LSubNetStr, LAddrInfo^.ifa_name, LAddrInfo^.ifa_flags);
end;
Id_PF_INET6: begin
TIdStackLocalAddressIPv6Ex.Create(AAddresses, TranslateTInAddrToString(PSockAddr_In6(LAddrInfo^.ifa_addr)^.sin6_addr, Id_IPv6), LAddrInfo^.ifa_name, LAddrInfo^.ifa_flags);
end;
end;
end;
LAddrInfo := LAddrInfo^.ifa_next;
until LAddrInfo = nil;
finally
AAddresses.EndUpdate;
end;
finally
freeifaddrs(LAddrList);
end;
end;
const
IFF_UP = $1;
IFF_BROADCAST = $2;
IFF_LOOPBACK = $8;
IFF_POINTOPOINT = $10;
IFF_MULTICAST = $8000;
{ TIdStackLocalAddressIPv4Ex }
constructor TIdStackLocalAddressIPv4Ex.Create(ACollection: TCollection;
const AIPAddress, ASubNetMask: string; AName: MarshaledAString; AFlags: Cardinal);
begin
inherited Create(ACollection, AIPAddress, ASubnetMask);
FFlags := AFlags;
if Assigned(AName) then
FIfaName := AName;
end;
function TIdStackLocalAddressIPv4Ex.IsPPP: Boolean;
// The network connection to the carrier is established via PPP
// so GPRS, EDGE, UMTS connections have the flag IFF_POINTOPOINT set
begin
Result := (FFlags and (IFF_UP or IFF_POINTOPOINT) = (IFF_UP or IFF_POINTOPOINT))
and (FFlags and (IFF_LOOPBACK) = 0);
end;
function TIdStackLocalAddressIPv4Ex.IsWifi: Boolean;
// WLAN connections support Multicast
// WLAN connections do not use PPP
// Filter out the loopback interface (just for completeness, in case the
// network enumeration is changed so that loopback is also included)
begin
Result := ((FFlags and (IFF_UP or IFF_MULTICAST)) = (IFF_UP or IFF_MULTICAST))
and (FFlags and (IFF_LOOPBACK or IFF_POINTOPOINT) = 0);
end;
{ TIdStackLocalAddressIPv6Ex }
constructor TIdStackLocalAddressIPv6Ex.Create(ACollection: TCollection;
const AIPAddress: string; AName: MarshaledAString; AFlags: Cardinal);
begin
inherited Create(ACollection, AIPAddress);
FFlags := AFlags;
if Assigned(AName) then
FIfaName := AName;
end;
function TIdStackLocalAddressIPv6Ex.IsPPP: Boolean;
begin
Result := (FFlags and (IFF_UP or IFF_POINTOPOINT) = (IFF_UP or IFF_POINTOPOINT))
and (FFlags and (IFF_LOOPBACK) = 0);
end;
function TIdStackLocalAddressIPv6Ex.IsWifi: Boolean;
begin
Result := ((FFlags and (IFF_UP or IFF_MULTICAST)) = (IFF_UP or IFF_MULTICAST))
and (FFlags and (IFF_LOOPBACK or IFF_POINTOPOINT) = 0);
end;
initialization
SetStackClass(TIdStackVCLPosixEx);
end.
请记住,如果WiFi接口连接到无线热点,也可能使用计量连接。
@DavidHeffernan监督那一个。谢谢 –
完美的作品。谢谢你的帮助塞巴斯蒂安。 – DanielH