簡體   English   中英

從struct addrinfo提取十六進制IP

[英]extract hex IP from struct addrinfo

我已經用數據填充了結構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數據存儲在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地址?

根據鏈接的問題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");
  }
}

這里查看inet_ntoa的實現:

#define UC(b)   (((int)b)&0xff)

char* net_ntoa(struct in_addr in) {
    static char b[18];
    register char *p;
    p = (char *)&in;
    snprintf(b, sizeof(b), "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
    return (b);
}

您只需更改為所需的格式(即十六進制),即可更改其實現以適合您的需求。

snprintf(b, sizeof(b), "%02X%02X%02X%02X", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));

請注意,他們的解決方案不是線程安全的,因為它使用函數靜態緩沖區作為輸出。 要使其具有線程安全性,請更改該函數以使用輸出緩沖區,並要求該緩沖區至少包含9個字符(十六進制輸出為8個字符,空終止符為1個字符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM