c - gethostbyname() 返回具有负地址的结构

标签 c gethostbyname

我正在编写一个程序来检查给定 url 或 ip 上的端口是否打开。为了获得给定 url 的 ip 地址,我使用了 gethostbyname()。当尝试查找本地主机的地址时,它会返回正确的值,但是,尝试查找远程主机的地址时,它通常会失败并返回一个带有负数的 ip 地址。例如:

/test.out google.com
ip: -40.58.-42.78

/test.out reddit.com
ip: -105.101.-127.-116

./test.out facebook.com
ip: 31.13.84.36

奇怪的是,最后一个有效。这是我的代码:

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

int main(int argc, char **argv)
{
    struct hostent *he;
    struct in_addr **addr_list;

    if ((he = gethostbyname(argv[1])) == NULL) {
        herror("gethostbyname");
        return 1;
    }

    printf("ip: ");
    for (int i = 0; i < he->h_length; i++) {
        printf("%d", he->h_addr_list[0][i]);
        if (i != he->h_length - 1) printf(".");
    }
    printf("\n");
}

还有,为什么h_addr_list的类型是char **?它不应该是一个整数,或者更好的是一个无符号整数吗?

最佳答案

IP 地址的组成部分是无符号字节,但在 struct hostent 中,它们存储为 char(即已签名)。这意味着值 128..255 被解释为负数。

您使用 %d 格式打印它们,该格式将值打印为带符号的,因为这是它接收它们的方式。当您将值传递给 printf() 时,将值转换为 unsigned char(或 unsigned int,如果您愿意):

printf("%d", (unsigned char)he->h_addr_list[0][i]);

您也可以使用 %u 而不是 %d(它将接收到的值视为 unsigned),但您仍然需要将要传递给它的值转换为 unsigned1:

printf("%u", (unsigned char)he->h_addr_list[0][i]);

另一种选择是强制 printf() 仅使用它获取的值的最低有效字节并将其打印为无符号,使用 "%hhu"。然而,这看起来更像是一种 hack,而不是正确的解决方案。


1 没有转换,因为 printf()variadic function ,作为参数 (he->h_addr_list[0][i]) 传递给它的值从 (signed) char 提升为 (signed) int。对于大于 127 的组件,使用 "%u" 打印它们会产生非常大的数字而不是负数。

关于c - gethostbyname() 返回具有负地址的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44763040/

相关文章:

c - 在这个简单的 C 程序中分配内存时我哪里出错了?

c++ - 从树上摘苹果

c - 二维动态字符串数组 realloc 导致错误

PHP gethostbyname 返回主机名而不是 IP 地址

c++ - gethostbyname 创建一个线程?

c - UDP Socket 广播和 ifaddrstruct

c - 如何用 C 读取 CSV 文件的第一个条目?

C - 像二进制数一样遍历 0 和 1 的数组

c - 为什么程序运行在if((hptr = gethostbyname(buffer)) == NULL)时就崩溃了

c - 打印 inet_ntoa 函数中的段错误