2017-06-26 8 views
1

与えられたURLまたはipのポートが開いているかどうかをチェックするプログラムを書いています。指定されたURLのIPアドレスを取得するために、私はgethostbyname()を使用しています。 localhostのアドレスを検索しようとすると正しい値が返されますが、通常は失敗したリモートホストのアドレスを検索しようとし、負の数のIPアドレスを返します。例:gethostbyname()は、負のアドレスを持つ構造体を返します。

/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_listchar **のタイプがある:ここに私のコードは?それは整数でなくてはならないし、符号なしのものでなければならないだろうか?

+0

おそらく文字列を印刷しようとしています。 –

+2

アドレスを文字列に変換するには、関数inet_ntoaを使用します。 – Barmar

答えて

4

IPアドレスのコンポーネントは符号なしバイトですが、struct hostentではchar(つまり、符号付き)として格納されます。これは、値128 .. 255が負の数として解釈されることを意味します。

%d形式を使用して印刷します。この形式では値を署名付きで印刷します。これは、これを受信する方法であるためです。 (ご希望の場合はunsigned int)あなたがprintf()に渡す時に値がunsigned charに変換:

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

また%u代わりの%dを(それが受け取るunsigned値として扱われます)を使用することができますが、あなたはまだする必要があり値がunsigned にに渡す変換:

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

別のオプションは、valのうち唯一の最下位バイトprintf()使用を強制することですそれは、"%hhu"を使用して、符号なしとして取得して印刷します。しかし、これは正しい解決策よりもハックに似ています。変換なし


printf()variadic functionあるため、引数(he->h_addr_list[0][i])として渡された値は、(signed) charから(signed) intに昇格されています。 "%u"を使用すると、127より大きいコンポーネントの場合、負の数ではなく非常に大きな数値が生成されます。

+1

'char'の符号性はコンパイラによって異なります。 –

2

この回答は具体的にはh_addr_listのタイプです。

gethostbynameを発明した古代BSDプログラマーの心に、それはIPアドレスだけでなく、あらゆる種類のネットワークアドレスを調べるために使われることになっていました。そのため、h_addrtypeもあります。 h_addr_list[n]の解釈はh_addrtypeに依存します。 h_addrtype==AF_INETの場合、アドレスはよく知っている4バイトのIPアドレス形式です。他のアドレスタイプの場合、それは他のものかもしれません。

char **タイプのh_addr_listは、「動的に割り当てられた不透明バッファの配列」と理解されるべきである。それはvoid **だったかもしれないが、まだvoidが発明されていなかったかもしれない。

明らかに、IPv4はIPv6が登場するまで心配していた唯一のネットワークプロトコルとなり、ホストルックアップインターフェイスを完全に置き換えることに決めました(getaddrinfo参照)。だから野生の野外で非AF_INETh_addrtypeを見る機会はほとんどありませんでした。

関連する問題