Windowsでのpingによる相手確認

 ネットワーク上にある別の機器からデータを取得して、 それに基づいて展示などの動作をする機器を自動運転しようとする場合、 相手機器との通信が正常にできるかどうか 直前に確認してから動作させたい場合がある。

 unix系OSなら、

if ping データ取得するべき相手機器
then 展示などの動作
fi
というように、pingを使った状況確認が可能である。 MS-DOS上で動作するCenterNET PC/TCP Ver.6でも、
PING -z データ取得するべき相手機器
IF ERRORLEVEL 1 GOTO 不調時の動作を記述した部分
展示などの動作
という形でpingが使える。

 ところが、Windows標準のpingではこの方法が使えない (最近のWindowsでは変わっているかもしれないが、 少なくとも手元のWindows95やWindows98ではダメ) 。 相手機器との通信に成功したかどうかに関わらず、 常に「正常終了」のリターンコードを返すからである。

 これでは困るので調べてみたところ、 手元のC++開発環境(Visual Studio 6.0)のヘルプ機能で検索できる MSDN(Microsoft Developper Network)のデータの中に 「Ping sample (Winsock SOCK_RAW echo)」というのがあった。 これはそのままコンパイルすると、オペレータが介入するまで 1000ミリ秒間隔で延々とpingし続けるコンソールアプリケーションになる。 これを微修正してコンパイルすることによって、 思い通りにリターンコードを返すpingを入手することができた。

 具体的な修正内容は以下の通りである。

  1. main()の最後の方で「while(1)」による無限ループがあるので、 これをループで無くする。ループの最後にある「sleep(1000);」は削除する。
  2. スコープが無限ループの中となっている変数があるので、 単純にmain()全体にスコープを有する変数に改める。
  3. 無限ループの中にある2つの「continue;」を、 「return 異常終了時のエラーコード;」に改める (main()末尾の「return 0;」が正常終了時の動作になる)。

 さて、手元でこの動作をさせたい機械が2つあって、 一方のWindows98機はこれで目的が達成された。 ところが、他方は古いWindows95で、Winsock2が入っていない。 そこで、Winsock1で動作させようと思って、 以下のように、更に修正を施してみた。

  1. 冒頭の「#include <winsock2.h>」を 「#include <winsock.h>」に改める。
  2. main()の最初の方にある「WSAStartup」の第1引数 「MAKEWORD(2,1)」を単純に「MAKEWORD(1,1)」に変える。
  3. その続きにある「WSASocket」を単純に「socket」に変える (引数は、単に第4引数以下を削除する)。
  4. 別ファイルになっている「Makefile」の中の 「ws2_32.lib」という記述を「wsock32.lib」に改める。 (当初、この修正を怠っていたところ、 目的環境でコマンドを実行させた途端に 「実行時エラー」というダイアログがコマンドプロンプトの窓とは別に出て、 コマンドが直ちに終了してしまった。)
そうすると、開発環境のWindows98では動作したのだが、 肝腎の目的環境では、エラーコード10044(WSAESOCKTNOSUPPORT)で 実行時エラーになってしまった。 ヘルプ等を調べてみると、Winsock1ではSOCK_STREAMとSOCK_DGRAMだけで、 SOCK_RAWはサポートされないらしい。ウムム……

 それにしても、Winsock2がインストールされてたら、 Winsock1のライブラリをリンクしてても SOCK_RAWを使ったコードが通るわけ? 変なの。


2003年9月11日初稿/2014年1月23日ホスト移転

戸田孝の雑学資料室へ戻る

Copyright © 2003 by TODA, Takashi