iOS设备的IP地址

时间:2015-05-29 18:17:03

标签: delphi firemonkey

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

@widi 如果在不同的语言平台上提出了类似的问题,那并不代表我指定的问题有答案 - 阅读标签 - 它说" delphi &# 34; "的 firemonkey &#34 ;.这就像在 C#中提问一样,并且很高兴在 COBOL 中获取代码示例。

1 个答案:

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