首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从DNS获取主机名的IP地址?

如何从DNS获取主机名的IP地址?
EN

Stack Overflow用户
提问于 2013-08-15 21:54:09
回答 2查看 12K关注 0票数 2

如果我在我的Delphi2006中使用GetIP('server-name')GetIP('google.com'),我有一个检索IP地址的函数。

但是现在我在Delphi-XE3上试了一下,它不工作了。有什么想法吗?

代码语言:javascript
复制
function GetIP(const HostName: string): string;
var
  WSAData: TWSAData;
  R: PHostEnt;
  A: TInAddr;
begin
  Result := IPNULL; // '0.0.0.0'
  WSAStartup($101, WSAData);
  R := Winsock.GetHostByName(PAnsiChar(HostName));
  if Assigned(R) then
  begin
    A := PInAddr(r^.h_Addr_List^)^;
    Result := string(WinSock.inet_ntoa(A));
  end;
end;

因为结果始终为'0.0.0.0',所以R似乎没有被赋值

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-08-16 04:30:05

这两个版本的Delphi之间的最大区别在于,现代的Delphi本身就使用宽的UTF-16编码字符串,而旧版本使用ANSI编码的字符串。

许多API函数同时具有wide和ANSI版本。但是你在Winsock中调用的函数只有8位。

通过显式使用8位文本编码,可以使代码像以前一样工作。

代码语言:javascript
复制
function GetIP(const HostName: string): string; 
var 
  WSAData: TWSAData;
  R: PHostEnt; 
  A: TInAddr; 
begin 
  Result := IPNULL; // '0.0.0.0' 
  WSAStartup($101, WSAData); 
  R := Winsock.GetHostByName(PAnsiChar(AnsiString(HostName))); 
  if Assigned(R) then 
  begin 
    A := PInAddr(r^.h_Addr_List^)^; 
    Result := WinSock.inet_ntoa(A); 
  end; 
end;

现在,细心的读者会说:

如果主机名包含非ASCII码字符,该怎么办?被这些相当弱的固定长度8位编码所约束,难道不是一种遗憾吗?

现在,推荐的将主机名转换为地址的函数是Unicode函数GetAddrInfoW

票数 11
EN

Stack Overflow用户

发布于 2018-03-07 00:19:37

这是一个独立的示例,我使用winsocks2和unicode支持来解析XE3-XE7上的IP地址。

它的性能不是很好,因为套接字支持在每次调用时都被初始化和反初始化,但是重构是微不足道的。

另外,请注意,它并不是为了便于维护而进行优化的。

代码语言:javascript
复制
uses
  Winapi.Winsock2;

type
  PAddrInfo = ^TAddrInfo;
  TAddrInfo = packed record
    ai_flags: integer;
    ai_family: integer;
    ai_socktype: integer;
    ai_protocol: integer;
    ai_addrlen: NativeInt;
    ai_canonname: PCHAR;
    ai_addr: PSOCKADDR;
    ai_next: PAddrInfo;
  end;

function GetAddrInfo(const nodeName: PCHAR; const serviceName : PChar; const hints: PAddrInfo; var result: PAddrInfo): integer; stdcall; external 'ws2_32.dll' name 'GetAddrInfoW';
procedure FreeAddrInfo(const addrInfo: PAddrInfo); stdcall; external 'ws2_32.dll' name 'FreeAddrInfoW';

function ResolveIpAddress(const hostName: string; const ipv6: boolean): string;
const
  BUFFER_SIZE = 32768;
var
  data: TWSAData;
  error: integer;
  requestError: integer;
  r: PAddrInfo;
  s: string;
  hints: TAddrInfo;
  buffer: TArray<byte>;
  length: DWORD;
begin
  error:= WSAStartup(MAKEWORD(2, 2), data);
  try
    if (error = 0)  then
    begin
      r:= nil;
      try
        ZeroMemory(@hints, sizeof(TAddrInfo));
        if (ipv6) then
          hints.ai_family:= AF_INET6
        else
          hints.ai_family:= AF_INET;

        requestError:= GetAddrInfo(PCHAR(hostName), nil, @hints, r);
        if (requestError = 0) then
        begin
          length:= BUFFER_SIZE;
          SetLength(buffer, BUFFER_SIZE);
          if (WSAAddressToString(r.ai_addr^, r.ai_addrlen, nil, @buffer[0], length) = 0) then
          begin
            setLength(buffer, length * 2);
            s:= TUnicodeEncoding.Unicode.GetString(@buffer[0]);
            exit(s);
          end
          else
            exit('0.0.0.0');
        end
        else
          exit('0.0.0.0');

      finally
        FreeAddrInfo(r);
      end;
    end
  finally
    if (error = 0) then
      WSACleanup();
  end;
end;
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18254209

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档