我需要获取iOS设备的IP地址。 GStack.GetLocalAddressList返回所有地址,包括Cellular接口的地址。 如何获取与wifi接口相关的地址(en0)?
@widi 如果在不同的语言平台上提出了类似的问题,那并不代表我指定的问题有答案 - 阅读标签 - 它说" delphi &# 34; "的 firemonkey &#34 ;.这就像在 C#中提问一样,并且很高兴在 COBOL 中获取代码示例。
答案 0 :(得分:1)
您必须实现自己的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类,其中包括适配器名称和一些有助于确定网络是蜂窝网还是wifi网络的功能。
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接口连接到无线热点,它也可能使用计量连接。