【问题标题】:gethostbyname() function returns empty buffergethostbyname() 函数返回空缓冲区
【发布时间】:2015-11-17 01:31:30
【问题描述】:

我是互联网编程新手,我正在尝试使用gethostbyname() 函数。当我在 gethostbyname 函数中输入诸如“www.yahoo.com”之类的字符串时,它可以正常工作,但是当我输入 char 数组时,它总是会返回一个空缓冲区。

  char hostname[100];
  struct hostent* h;
  gethostname(hostname, sizeof hostname );
  printf("Hostname: %s\n", hostname);
  h = gethostbyname(hostname);

知道如何解决这个问题吗?

【问题讨论】:

  • gethostname() 返回的主机名是否有效?您没有检查返回值是否有错误。无论如何,为gethostname() 报告的主机名调用gethostbyname() 毫无意义。这是检索本地计算机 IP 地址的常见错误方法。您应该使用GetAdaptersInfo/GetAdaptersAddresses (Windows)、getifaddrs() (*Nix) 或其他类似的特定于平台的函数来直接枚举本地接口。
  • 是的,gethostname 返回正确的主机名,但 gethostbyname 总是返回 null。
  • 您真正想要完成什么? gethostbyname() 执行 DNS 查找。使用gethostname() 报告的主机名不能保证返回有效的 DNS 结果,具体取决于您机器的 DNS 设置。在某些平台上,使用本地主机名调用gethostbyname() 将返回结果,而在某些平台上则不会。如果失败,请检查WSAGetLastError()/h_errno 找出原因。无论如何,gethostbyname() 无论如何都已弃用,您应该改用getaddrinfo()
  • @RemyLebeau 我只是想找出我正在运行的机器的 IP 地址。无论如何,我想我会改为检查 getaddrinfo(),谢谢!
  • @SH.C 你机器的主机名是什么?

标签: c sockets gethostbyname


【解决方案1】:

您的服务器无法自行解析。 “修复”此问题的最常见方法是将其自己的名称放入其主机文件中。虽然出于各种原因这是一个好主意,但真正应该解决的根本问题。

  1. DNS 搜索列表通常应该设置为包含主机名的域名 - 或者 - 主机名本身应该是完全限定的。
  2. 应为主机正确设置 DNS。

这使它根本不是真正的 C 问题,而是服务器配置问题。那就关掉吧。

【讨论】:

  • mods注意——这个答案在serverfault的传输目标中有效。可能不会得到很高的投票,但总比没有回答要好。
【解决方案2】:

在 linux 程序员手册中,该函数具有以下声明:

struct hostent *gethostbyname(const char *name);

这意味着参数必须是一个字符数组(或外行术语的字符串)。调用函数时可以直接使用“yahoo.com”等带引号的字符串。

以下代码是一个关于 gethostbyname 如何工作的工作示例:

#include <stdio.h>
#include <string.h>
#include <netdb.h>

int main(){
  struct hostent* h=gethostbyname("yahoo.com");
  printf("Hostname: %s\n", h->h_name);
  printf("Address type #: %d\n", h->h_addrtype);
  printf("Address length: %d\n", h->h_length);

  char text[50]; // allocate 50 bytes (a.k.a. char array)
  strcpy(text,"bing.ca"); //copy string "bing.ca" to first 7 bytes of the array
  h=gethostbyname(text); //plug in the value into the function. text="bing.ca"
  printf("Hostname: %s\n", h->h_name);
  printf("Address type #: %d\n", h->h_addrtype);
  printf("Address length: %d\n", h->h_length);

  return 0;
}

我调用了两次。一次用于 yahoo.com,一次用于 bing.ca,我检索了主机名、地址类型号和地址长度(即存储 IP 所需的字节数)。

为了调用 bing 地址,我分配了一个 char 数组,用一个字符串填充它,然后将该 char 数组作为参数传递给函数。

【讨论】:

  • 那么是gethostname的问题吗?在我的情况下,我不知道我的主机名,所以我不能将它硬编码到一个 char 数组中。当我使用 gethostname 尝试您的代码时,它仍然返回 null。
  • 运行代码的(虚拟?)机器上是否有可用的互联网连接?您可以从gethostname() 获取值,然后将值(gethostname 函数的第一个参数)直接插入gethostbyname(),就像您在代码中显示的那样,但在“sizeof”之后将括号括在主机名周围。但我最终猜测您的互联网质量在执行该功能时很差。
  • 是的,我的互联网连接正常。那么当你将 gethostname 添加到你的代码中时它会起作用吗?
  • 这不是有或没有互联网连接的问题。无法保证gethostbyname() 始终可以将gethostname() 报告的主机名解析为所有平台上的IP 地址。所以不要尝试,反正这是错误的方法。请改用getifaddrs() 或类似函数。
【解决方案3】:

它返回 NULL 的一个很好的原因是您传递的主机名不正确。 有时即使执行 hostname -v 也不会给出正确的主机名。

尝试以下操作:

cat /etc/hosts

这将显示您的输出为:

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain

上面输出中 127.0.0.1 旁边的“localhost”是您的主机名。这将与 gethostbyname 完美配合。

【讨论】:

    【解决方案4】:
    WSADATA wsaData;
    int error;
    if ((error = WSAStartup(MAKEWORD(1, 1), &wsaData)) !=0)
    {      
        printf("Error %d in WSAStartup, result will fail\n",error);
    }   
    char hostname[100];
    struct hostent* h;
    gethostname(hostname, sizeof hostname );
    printf("Hostname: %s\n", hostname);
    h = gethostbyname(hostname);
    

    【讨论】:

    • 此代码是特定于 Windows 的。也许OP有Linux系统!
    • 仅仅代码不是答案。你必须解释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-17
    • 2017-01-01
    • 2015-06-01
    • 2012-11-23
    • 1970-01-01
    • 1970-01-01
    • 2015-08-26
    相关资源
    最近更新 更多