我已使用数据填充了我的结构struct addrinfo **res
:
err = getaddrinfo(argv[1], NULL, &hints, &res);
如果我想打印IP地址,我可以使用
addr.s_addr = ((struct sockaddr_in *)(res->ai_addr))->sin_addr.s_addr;
printf("ip address : %s\n", inet_ntoa(addr));
然后打印例如10.111.1.11
。但我需要十六进制格式的IP,即0A6F010B
。
我想出了以下内容,它确实会以十六进制格式打印IP:
for (i=0; i<32; i=i+8)
printf("%02X",(addr.s_addr>>i) % 256) ;
但在我看来,我的方法是不必要的复杂。我需要两个步骤(两次转换)。如果可能,我想简化我的代码,并直接从res->ai_addr->sa_data
打印十六进制IP(无需先将数据存储在addr.s_addr
中)。
我知道数据存在于res->ai_addr->sa_data
中。我可以打印出来:
for (i=0; i<14; i++)
printf("%d", res->ai_addr->sa_data[i]);
printf("\n");
我得到以下输出(对应10.111.1.11
):
001011111100000000
但格式并不像前面的例子那样简单。例如,对于172.25.0.31
,我得到了这个输出:
00-842503100000000
如何将此乱码转换为十六进制IP地址?
答案 0 :(得分:2)
根据linked question和this description of sockaddr
,您需要进行一些动态类型修改。使用正确的类型,它可能看起来像这样:
struct addrinfo * res;
err = getaddrinfo(argv[1], NULL, &hints, &res);
// check that the operation succeeded
assert(err == 0);
// check that the dynamic type is AF_INET
assert(res->ai_addr->sa_family == AF_INET);
// downcast
struct sockaddr_in * p = (struct sockaddr_in *)(res->ai_addr);
// done
printf("Address: %08X (%s)\n", p->sin_addr.s_addr, inet_ntoa(p->sin_addr));
执行正确动态类型选择的更完整示例可能如下所示:
char str[128];
switch (res->ai_addr->sa_family)
{
case AF_INET:
{
struct sockaddr_in * p = (struct sockaddr_in *)(res->ai_addr);
if (inet_ntop(p->sin_family, &p->sin_addr, str, sizeof str) == NULL)
fprintf(stderr, "Error in inet_ntop: %s\n", strerror(errno));
else
printf("Address: %08X (%s)\n", p->sin_addr.s_addr, str);
break;
}
case AF_INET6:
{
struct sockaddr_in6 * p = (struct sockaddr_in6 *)(res->ai_addr);
if (inet_ntop(p->sin6_family, &p->sin6_addr, str, sizeof str) == NULL)
fprintf(stderr, "Error in inet_ntop: %s\n", strerror(errno));
else
printf("Address: %s\n", str);
break;
}
default:
{
fprintf(stderr, "Unrecogized address family, skipping.\n");
}
}
答案 1 :(得分:1)
查看inet_ntoa
here的实施:
#define UC(b) (((int)b)&0xff)
char* net_ntoa(struct in_addr in) {
static char b[18];
register char *p;
p = (char *)∈
snprintf(b, sizeof(b), "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
return (b);
}
您可以通过交换所需的格式(即hex:
)来更改其实现以满足您的需求snprintf(b, sizeof(b), "%02X%02X%02X%02X", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
请注意,他们的解决方案不是线程安全的,因为它使用函数静态缓冲区作为输出。要使其成为线程安全的,请更改函数以获取输出缓冲区,并要求缓冲区至少包含九个字符(十六进制输出为八个,另一个为空终止符。