開発環境:VC++6.0 WindowsXP
WindowsNT系のソフトウェアを開発しています。
現在作っているソフトウェアの仕様の中に、
IP:192.168.1.100~192.168.1.109
までの10個のマシンからファイルを拾ってきて結合するというものがあります。
困っているのは、
1.常にマシンが10個存在するわけではない
2.マシンが存在してもファイルがあるかどうかは分からない
という事です。
通常のfopen()でファイルを開きにいっても、ファイルがない場合ネットワーク越しだと
関数が帰ってくるのに時間がかかってしまいます。
_filefind()なども使ってみたのですが、同じ結果です。
時間がかからずにネットワーク越しのファイルの有無を調べる方法はないでしょうか?
よろしくお願いします。
ネットワークのファイルを見に行く、相手がいるかどうか判らない、ということなら
相手が居ないとき時間がかかるのは仕方ない話です。
その相手先ホストはダイアルアップでつながっているのかもしれませんし、
あまりにあっさりタイムアウトされてしまっては逆に困ってしまいます。
たとえば、以下のようにすれば少しはましかもしれません。
(1)ICMPを用いて、相手マシンのネットワーク上での存在を確認する。
(2)マシンの存在が確認できた場合、FindFirstFile(_filefind)で、ファイルの検索を掛
ける。
(3)ファイルが存在する場合、ファイルのオープンをする。
ソケットレベルの話になってしまいますが、存在しないIPアドレスに対して、connect()を実行
すると、
デフォルトで90秒程度、connect()から戻らなくなります。
恐らく、fopen()や_filefind()も内部的にconnect()を用いて接続を試み、
そのために関数から返ってこなくなっていると思われます。
ICMP は router が拒絶したりウィルス対策ソフトが拒絶したりして却下な場合が。
ping が通ったとしてもホストのデーモンが生きてる保証は無いしやっぱり却下な場合が。
ネットワークの基本は「つなぎたいプロトコルで直接つなぎにいく」であり、
それ以外の手段を取るのは、個人的には推奨できません。
> ping が通ったとしてもホストのデーモンが生きてる保証は無いしやっぱり却下な場合
が。
詳細な仕様等はわかりかねますが、とりあえず私の経験則で。
先のレスにあるように、私も通信のソフトを組んだことがあり、その際に、
存在しないIPアドレスに対してTCPでconnect()を行うとconnect()からなかなか制御がも
どりませんでした。
しかし、指定したIPアドレスのマシンが存在するが、そのマシン上でconnect()先のサー
バソフト(サービス)が動いていない場合、
connect()はすぐにエラーを返してくれたということがありましたので。
> ICMP は router が拒絶したりウィルス対策ソフトが拒絶したりして却下な場合が。
これに関してはご指摘の通り、パーソナルFWソフト等で拒絶される可能性がありますね。
> ネットワークの基本は「つなぎたいプロトコルで直接つなぎにいく」であり、
> それ以外の手段を取るのは、個人的には推奨できません。
基本的に同意いたしますが、今回の場合、タフガイさんの書き込み内容に、
特にプロトコルに関する記述がないので、標準的な方法での解決案としてどうかと。
ネットワークに詳しくないので推測ですが、
fopenではなくWin32APIの非同期のファイルアクセスは駄目なの?
タイムアウトの長さを変えたりキャンセルが出来るはず。
出来るか知らんがマシン10台に一斉にアクセスして
処理可能なものから処理していくとか。
あるいはスレッド10個つくって一斉にfopenする。
そして処理可能なものから処理していくとか。
fopenが1個ぶん待たされることには変わりないけどね。
みなさん、レスありがとうございます。
最初に、間違いがあったので訂正します。
_filefind()→_findfirst()
の間違いでした。すみません。
ICMPについて、あまり知らなかったので後学の為にも試してみたのですが、
どうもインクルードしたヘッダが開けないとエラーが出て使えないですね。
ライブラリもリンクしてみたのですが、どうにも・・・
>(1)ICMPを用いて、相手マシンのネットワーク上での存在を確認する。
どの様な関数を使うのかまで調べられていないのですが、この場合はすぐに応答が返っ
てくるのでしょうか?
それとも、pingの応答待ちと同じ程度の時間がかかるのでしょうか?
>fopenではなくWin32APIの非同期のファイルアクセスは駄目なの?
>fopenが1個ぶん待たされることには変わりないけどね。
実際にはfopen()でファイルを開いてから読んでいるわけではなく、ファイルの有無を調
べる一つの方法として使っていたんです。
ファイルはiniファイルでして、GetProfileString()を使いたいんですね。
ですので、非同期も今回は使えないんです。
>あるいはスレッド10個つくって一斉にfopenする。
これについては考えもしませんでした。
頭が固くなってしまっていました。柔軟性が必要ですね。
できたら待ち時間はほとんどない方がいい(アプリ起動時に行う処理なので)ですが、
どうにもならない場合はその方法でユーザーに了解を得られるように頑張ってみます。
また、設計的にもその方法が使えるか再考しないと何とも言えないのですが。
もう少し色々調べてみますが、何かいい方法がありましたらご協力下さい。
よろしくお願いします。
>>(1)ICMPを用いて、相手マシンのネットワーク上での存在を確認する。
>どの様な関数を使うのかまで調べられていないのですが、この場合はすぐに応答が返っ
てくるのでしょうか?
>それとも、pingの応答待ちと同じ程度の時間がかかるのでしょうか?
ICMPとはpingの中で使われているプロトコルです。
というか、ICMPを利用したソフト(?)のひとつがpingです。
で、要はpingと同じことを実装すればどうか、という話です。
pingのコードは、検索すればどっかにサンプルが見つかると思いますので。
KING・王さまにほぼ同意。
今回の案件ではローカル IP アドレスが書かれているので LAN 限定ぽいっすから
とりあえず ping ってみてもいいかもしれません。
個人的には限りなく無駄であると思います。俺ならそういう実装を決してしません。
ping が役に立つのはマシンが死んでる場合に限られますから。
1.マシンが生きてて daemon が走ってないとき→
△connect するとすぐ拒絶の返事が返ってくるので ping を打つ必然無し
2.マシン/daemon が両方生きてて ICMP に応答しないとき→
×connect に反応できるのに ping チェックで刎ねてしまうと誤動作になる
3.マシンが死んでるとき→
○とりあえず速度向上にはつながるだろう
俺なら2と3の二者択一になってしまうのなら誤動作しないほうを取ります。
とりあえずタフガイさま向け参考
http://www.pc-view.net/Network/030610/index.html
お二方、またまた親切なレスありがとうございます。
ICMPについてのリンク・説明ありがとうございます。
リンク先もきっちり読ませて頂きました。
ネットワーク関係には(にも?)疎いもので、大変参考になりました。
とりあえず、現状ではどの方法でも時間がかかってしまうのは免れない旨を明日にでも
客先に伝えて、仕様考え直してもらうように伝えてみます。
また状況が変わりましたらご報告申し上げます。