获取错误的IP地址

时间:2014-01-30 21:34:43

标签: delphi sockets ipv6 ipv4

我尝试自动检测并报告Delphi套接字编程的IPv6可用性。

对于" localhost",以下代码返回" 1700 ::"对于IPv6和" 2.0.0.0"对于IPv4。此地址用于简单测试,应该为我的机器返回:: 1或127.0.0.1。我在调用代码中没有收到任何套接字API错误,所以我试图弄清楚我在尝试转换" localhost"时做错了什么。到各种IP地址。我正在使用Indy标题。

类型声明是:

TLSocketAddress = record
  case Integer of
    AF_INET:
      (IPv4: TSockAddrIn);
    AF_INET6:
      (IPv6: TSockAddrIn6);
end;

TLIpInfo = record
private
  function GetFamily: TProtocolFamily;
public
  Address : TLSocketAddress;
  HostName: string;
  Machine: string;
  IP6 : string;
  IP4 : string;
  Port : integer;
  Error : integer;
  property Family : TProtocolFamily read GetFamily;
end;

,检索程序为:

function GetIpInfo(
  const AHostName : string;
  const APort     : integer
  ): TLIpInfo;
var
  nameRet   : PAnsiChar;
  ptr       : Pointer;
  Hints     : TAddrInfoW;
  AddrInfo  : PAddrInfoW;
  NextInfo  : PAddrInfoW;
  RetVal    : Integer;
  ip,
  machine   : string;
  namelen   : integer;
begin
  ZeroMemory(@Result, SizeOf(Result));
  FillChar(Hints, SizeOf(Hints), 0);
  Hints.ai_family := AF_UNSPEC;

  AddrInfo := nil;
  RetVal := GetAddrInfo(PWideChar(AHostName), nil, @Hints, @AddrInfo);
  if RetVal = 0 then
  try
    Result.HostName := AHostName;
    Result.Port := APort;
    NextInfo := AddrInfo;
    while NextInfo <> nil do
    begin
      if (NextInfo.ai_family = AF_INET) or (NextInfo.ai_family = AF_INET6) then
      begin
        if (Result.Machine = '') then
        begin
          SetLength(machine, NI_MAXHOST);
          RetVal := GetNameInfo(NextInfo.ai_addr, NextInfo.ai_addrlen,
            PChar(machine), NI_MAXHOST, nil, 0, 0);
          if (RetVal <> 0) then
          begin
            NextInfo := NextInfo.ai_next;
            continue;
          end;
          Result.Machine := PChar(machine);
        end;

        if NextInfo.ai_family = AF_INET then
        begin
          ptr := PSockAddrIn(NextInfo.ai_addr);
          namelen := INET_ADDRSTRLEN;
          SetLength(ip, namelen);
        end
        else
        begin
          ptr := PSockAddrIn6(NextInfo.ai_addr);
          namelen := INET6_ADDRSTRLEN;
          SetLength(ip, namelen);
        end;

        nameRet := inet_ntop(NextInfo.ai_family, ptr, PChar(ip), namelen);
        if (nameRet = nil) then
        begin
          NextInfo := NextInfo.ai_next;
          continue;
        end;

        if (NextInfo.ai_family = AF_INET6) then
          Result.IP6 := PChar(ip)
        else
          Result.IP4 := PChar(ip);
      end;
      NextInfo := NextInfo.ai_next;
    end;
  finally
    FreeAddrInfo(AddrInfo);
  end;
end;

1 个答案:

答案 0 :(得分:1)

我知道这对作者来说可能为时已晚,但我今天也遇到了同样的问题,并注意到你将指向整个 ADDRINFO 结构的指针传递给 inet_ntop 但是,您应该只将指针传递给二进制地址 因此,对 IPv4 地址的 intet_ntop 的调用应为:

inet_ntop(NextInfo.ai_family, @PSockAddrIn(NextInfo.ai_addr).sin_addr, PChar(ip), namelen)

IPv6 应为:

inet_ntop(NextInfo.ai_family, @PSockAddrIn6(NextInfo.ai_addr).sin6_addr, PChar(ip), namelen)