人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

Visual studio 2015でPingプログラムを試しています。 以下のurlを参照しています。コンパイルが通り実行しまいた。host名でのpingは成功しました。ただし、IPアドレスでは失敗します。理由はDNSやHOSTSから名前が引けてないからです。実施には通信機器などDNS登録がないものも多々あるのでこれでは使いもになりません。
http://www.winsock2.org/samples/Ch05/PingI/pingi.c

iaDest.s_addr = inet_addr(argv[1]);
if (iaDest.s_addr == INADDR_NONE)
pHost = gethostbyname(argv[1]);
else
pHost = gethostbyaddr((const char *)&iaDest, sizeof(struct in_addr), AF_INET);
if (pHost == NULL){
fprintf(stderr, "\n%s not found\n", argv[1]);
WSACleanup();
FreeLibrary(hndlIcmp);
return;
}

// 動作状況をユーザーに表示
printf("\nPinging %s [%s]", pHost->h_name,
inet_ntoa((*(LPIN_ADDR)pHost->h_addr_list[0])));

// IPアドレスをコピー
dwAddress = (DWORD *)(*pHost->h_addr_list);

一番簡単な方法はdwAddressに直接argv[1]を入れればいいtおもっています。単なる代入式(=)ではうまくいきませんでした。DWORDでCastしてもだめでした。

どなたか、解決方法をご教授いただけますか?

●質問者: mai_mai_mail
●カテゴリ:コンピュータ
○ 状態 :終了
└ 回答数 : 1/1件

▽最新の回答へ

1 ● soqans
●100ポイント

直接IPアドレスを指定する場合は少し変更する必要がありそうです。質問の中で指摘があるとおりIPアドレスから逆引きできない場合に失敗する状態ですのでその場合は指定されたIPを直接使ってpingを発行するようにすればよいと思います。

具体的には修正後のコードを書いてみますと


struct in_addr iaDest,iaBuf; // インターネットアドレス構造体(バッファ部分追加)

iaDest.s_addr = inet_addr(argv[1]);
if (iaDest.s_addr == INADDR_NONE)
pHost = gethostbyname(argv[1]);
else
pHost = gethostbyaddr((const char *)&iaDest,
sizeof(struct in_addr), AF_INET);
if (pHost == NULL)
{
if(iaDest.s_addr == INADDR_NONE)
{
fprintf(stderr, "\n%s not found\n", argv[1]);
WSACleanup();
FreeLibrary(hndlIcmp);
return;
}
else{
// アドレスをバッファにコピー
memcpy(&iaBuf,&iaDest,sizeof(struct in_addr));
dwAddress = (DWORD *)(&iaBuf);

// 動作状況をユーザーに表示
printf("\nPinging [%s]",inet_ntoa(iaBuf));
}
}
else
{
// 動作状況をユーザーに表示
printf("\nPinging %s [%s]", pHost->h_name,
inet_ntoa((*(LPIN_ADDR)pHost->h_addr_list[0])));

// IPアドレスをコピー
dwAddress = (DWORD *)(*pHost->h_addr_list);
}


説明を書いておきますと引数としてIPv4形式のアドレス文字列("192.168.0.1"など)を与えるとinet_addr関数がそれを32bitの値に変換します。値に変換した場合はgethostbyaddr関数で逆引きをします。このとき元のプログラムでは失敗したときは終了するようになっていますがこの修正版ではその場合は逆引き失敗を無視してdwAddressにiaDestをコピーしたiaBuf(関数の先頭でiaDestの宣言に追加する)のポインタを格納するようになっています。

これはIcmpSendEcho関数の第2引数として渡さなければならないのがin_addr構造体そのもので、in_addr構造体が32bit値であることを利用して同じ32bit値のDWORDのポインタを参照する、という形で処理されているからです。(おそらくh_addr_listからのデータの受け取りを考えているのでしょうが…)

動作を追ってみればわかりますが逆引きに失敗したときはいったんin_addr構造体であるiaBufのポインタを格納してIcmpSendEcho関数の引数としてポインタを参照することで事実上in_addr構造体そのものを参照する、という動きになります。

DWORD *を使っているあたりが少し読みづらいポイントかもしれません。

関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ