【发布时间】:2014-02-23 10:14:54
【问题描述】:
我正在尝试自动检测和报告用于 Delphi 套接字编程的 IPv6 可用性。
对于“localhost”,以下代码返回 IPv6 的“1700::”和 IPv4 的“2.0.0.0”。此地址用于简单测试,应该为我的机器返回 ::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;
【问题讨论】:
-
你为什么要查找“localhost”?这可以在
/etc/hosts、DNS等中设置。 -
确实,如果有人愿意,可以将 LocalHost 设置为指向
8.8.8.8 -
另外,如果您在域中,您可能会收到
localhost.example.com,在这种情况下,您可以尝试localhost.。 -
这是通用的本地测试代码。本地主机仍然是默认的,所以这些查找值是不正确的。 localhost 都无法访问这些值,默认情况下 IIUC 应该是 ::1 或 127.0.0.1,这就是它们在我的机器上的值。
-
尝试打开命令提示符并查看
ipconfig /all实际报告的内容,您可能会看到1700::和2.0.0.0列出。如果存在多个 IP,您的代码将存储每种类型的最后找到的 IP,并且如果找到另一个相同类型的 IP,您不会检查是否已经存储了 IP。由于您正在对"localhost"进行 DNS 查找,因此除非您安装了环回适配器,否则您实际上不可能在getaddrinfo()的输出中看到::1和127.0.0.1。