2015-05-29 187 views
0

我需要获取iOS设备的IP地址。 GStack.GetLocalAddressList返回所有地址,包括Cellular接口的地址。 如何获得与wifi接口(en0)相关的地址?iOS设备的IP地址

@widi 如果类似的问题被要求在不同的语言平台,但这并不意味着不存在为我指定了一个答案 - 读取标签 - 它说:“德尔福”“firemonkey ”。这就像在C#中问一个问题,并欣喜地获得COBOL中的代码示例。

+0

@DavidHeffernan监督那一个。谢谢 –

+0

完美的作品。谢谢你的帮助塞巴斯蒂安。 – DanielH

回答

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类,包括适配器名称和一些功能来帮助决定一个网络是蜂窝或无线网络连接。

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接口连接到无线热点,也可能使用计量连接。

相关问题