ネットワークドライブ再接続時にエラーが発生する件について、
現象が回避できず解決策も見つからず困っております。
皆様のお知恵をお借りできないでしょうか。。。
【環境】
サーバ :Win XP (SP2)
クライアント:Win XP (SP2)
使用言語 :VC++ 6.0
【現象】
ある一定の間隔(1sec程度)で、ネットワークドライブのアクセスチェックを行うプログラムを
作成したのですが、プログラムを動作させ続けたまま何もPCを操作せずに、置いておくと
1日程度経過後にそのチェックでエラーが発生してしまいます。再接続の仕組みを入れてはいる
のですが、復旧できていませんでした。
【コーディング内容】
・ネットワークドライブのアクセスチェック処理
1._chdrive及び_chdir関数を使用し、ネットワークドライブのアクセスチェック及び
ネットワークドライブ上のディレクトリにアクセスできるかチェックを行います。
2.1.の結果、-1がリターンされてきた場合、再接続処理を行う。
・ネットワークドライブ再接続処理
1.WNetGetConnection関数を使用し、ネットワークパスの取得を行います。
2.NETRESOURCE構造体(仮に変数をaとします。)に値をセットします。
a.dwType = RESOURCETYPE_DISK;
a.lpLocalName = localDriveName.GetBuffer(0);
a.lpRemoteName = chrRemote;
a.lpProvider = NULL;
3.WNetAddConnection2関数を使用し、再接続を行います。
WNetAddConnection2(&nr,
NULL,
NULL,
0);
ネットワークドライブ再接続時にエラーが出る場合は、WNetAddConnection2関数の戻り値が
ERROR_ALREADY_ASSIGNED(既に接続済み)となっていました。
以上、宜しくお願い致します。
症状だけから判断すると典型的リソースリークです。
ハンドル数とかが無制限に増えていないかどうかをチェック。
tetrapod様、ご回答ありがとう御座います。
確かに、この症状が発生するとメモリ消費が激しくなり、最終的にはアプリケーションが
ダウンしてしまいます。
どのハンドルが怪しそうか、教えて頂けないでしょうか。
※質問ばかりで、申し訳ありません。
以上、宜しくお願い致します。
ソース無いのにどれが怪しいかなんて俺らにわかるわけないぢゃん。
そんなのは自分で調べておくんなまし。
Open してるけど Close してないのがあれば、それが原因。
ソース開示するからデバッグしてってのはお断り。
コーディング以前の話として仕様レベルでおかしいと思う。
1秒に1回アクセスなんてトラフィック量を増大させるだけで無駄っぽいし、
そもそもアクセスできない=切断された とは限らないよ。
だから再接続しに行くこと自体がヘン。
ネットワークドライブのアクセスチェックのためだけにソフトでネットワーク接続
をしなければ駄目ですか?
ネットワークドライブのアクセスチェックが完了して処理のためならわかりますが
ソフトで使うネットワークドライブですからマニュアルもしくはiniファイルやレジストリー
登録するぐらいに決まっているはずですよね。
WINDOWSのOSレベルできちんとネットワークドライブとして登録振れば、普通の
ディレクトリー検索でチェックできるのと思います。
多分、ここで出てきている話は、\\の後にPCの名称を指定して接続するような接続の仕方
かなぁと思うんですが、
ローカルデバイスと違ってネットワーク先のデバイスの場合、必ず接続できると言う
類のものではありませんし、ネットワークの構成によっては接続数の上限等の関係で
アクセスできなくなることもありえると思います。
GATEWAYが限られたリソースを有効活用するために使用していない接続を切って
他の接続の為に回すなんて事もありえるでしょうし。
なので必ず接続できると言う類のものではないし、必ず利用できるデバイスと言う
わけでも無いという事を前提に設計しておかないといけないと思います。
接続できないとシステムとして成立しないような設計をしているならそれがそもそもまず
いと思います。
そういう意味で仕様的にもっと考え直す必要があると思います。
tetrapod様、ご回答ありがとう御座います。
>Open してるけど Close してないのがあれば、それが原因。
特別に何かをOpenしたりはしておりません。
>ソース開示するからデバッグしてってのはお断り。
それは確かに仰るとおりだと思っています。
※デバックまでお願いしたら、私の仕事がなくなってしまいますし。
WNetGetConnection、WNetAddConnection2の使用方法が間違っているのかと思い、
先程のご質問をさせて頂きました。(後処理等が抜けている等。)
>そもそもアクセスできない=切断された とは限らないよ。
>だから再接続しに行くこと自体がヘン。
そうだったんですか・・・
・・・と言う事は、アクセスできない要因が切断以外にもあると言う事ですよね。
ディスクにアクセスできない = ドライブを認識していない(切断?)と思っていました。
_chdrive及び_chdir関数を実行するとエラーとなる、他の要因として
どのような事があるのでしょうか?
※MSDNには、エラーの時は-1しか書いてなかったので・・・
先程ネット検索をしていたら、XPの機能として
「ログオン時間の有効期間が切れるとクライアントを切断する」の記事を見つけました。
これの影響で切れている可能性もあるのではとも考えていますが、断言できないのが痛い所で
す。
ITO様、ご回答ありがとう御座います。
> ネットワークドライブのアクセスチェックのためだけにソフトでネットワーク接続
>をしなければ駄目ですか?
元々、手動でサーバ側にはネットワークドライブを割り付けています。
しかし、エラーケースとしてアプリケーション動作中に何らかの要因で
ネットワークドライブ先のファイルにアクセスできなくなった事を想定し、
再接続させる仕組みを組み込んでおります。
※現在のコーディングはネットワークドライブ先のファイルアクセスを行うたびに、
必ず_chdrive及び_chdir関数を呼び出しています。
この仕組みは、ファイルOPENに失敗した時のみに変更しようと考えております。
権限が無い (途中で剥奪された) とか
ファイル存在を確認→→→→→→→→→→→ファイルオープンは失敗とか
別ユーザにより削除
ネットワーク的に物理的障害が発生してると
ファイルオープンが失敗するけど、再接続も失敗するとか
接続に1秒以上の時間を要すると多重に接続しないだろうかとか
ぱっと思いつく程度でこれくらいはある。
真剣に考えればもっともっとありそうだしね。
ウチでは samba server のネットワーク接続において、
無アクセス時間10分でセッション自動切断を設定してる
smb.conf : deadtime=10
でも、ふつーはアクセスしようとしただけで自動的に再接続される
例 : CreateFile で \\Server\share\file を開こうとするだけで再接続される
例 : chdir しようとするだけで再接続される
し、この設定で今まで問題出たこと無いんだけどな。
自分での再接続が本当に必要なの?
PATIO様、ご回答ありがとう御座います。
>接続できないとシステムとして成立しないような設計をしているならそれがそもそもまず
>いと思います。
その通りだと思います。3年前から動いているシステムの為、あまり深くは考えずに
動いているから大丈夫だろうと思っていましたが、色々不味い点があったようです。
>そういう意味で仕様的にもっと考え直す必要があると思います。
確かに、仕様から見直す必要がありそうなのですが、
既にアプリケーションを納品してしまった為、
1から仕様を見直すのは難しい状況です。
tetrapod様、ご回答ありがとう御座います。
>権限が無い (途中で剥奪された) とか
>ファイル存在を確認→→→→→→→→→→→ファイルオープンは失敗とか
> 別ユーザにより削除
>ネットワーク的に物理的障害が発生してると
>ファイルオープンが失敗するけど、再接続も失敗するとか
>接続に1秒以上の時間を要すると多重に接続しないだろうかとか
確かに、上げて頂いた中にも発生しそうな問題がいくつかあります。
この現象発生時に、まずネットワーク的に物理的障害があったのではと考えて、
Hubの交換を行いました。
数日間は何も起こりませんでしたが、再度現象が発生した為に
アプリケーション側に問題がありそうだという事で調査を始めました。
>でも、ふつーはアクセスしようとしただけで自動的に再接続される
>例 : CreateFile で \\Server\share\file を開こうとするだけで再接続される
>例 : chdir しようとするだけで再接続される
>し、この設定で今まで問題出たこと無いんだけどな。
>
>自分での再接続が本当に必要なの?
この仕組みを作成する以前に、ネットワークドライブ先を指定してchdirやCreateFileを
実行するとエラーが発生するパターンがありました。
※エラー発生時、エクスプローラ上ではネットワークドライブに「X」表示がされていました。
打合せの結果、「ネットワークドライブが切れていると認識している為にエラーと
なっているのではないか?ネットワークドライブの再接続処理等が必要なのではないか?」
と言う方向に話が進み、この機能を実装する事になりました。
この機能を実装後、エクスプローラ上でネットワークドライブに「X」表示がされていても
問題なく動作するようになったのですが、今回の現象が発生するようになりました。
>特別に何かをOpenしたりはしておりません。
Connectは、ある意味Openと同じことです。
大抵の処理は、後始末まで考えておくべきでしょう。
まして、この場合は1OSどころかネットワークに接続する全て端末に影響する操
作です。
下手を打つと何が起こるかわからない処理である以上から慎重すぎるほど慎重
にやっても損は無いと思います。
気になるのは、エラーが帰ってきたから、「”とりあえず”再接続」という考え方で
す。
自分のパソコンの中だけで動かすならそれも許されるかも知れませんが、貴方の
口ぶりだと仕事です。
「とりあえずこうしたら動いたけど、別の場所が駄目になった」、では洒落にならな
いと思いますが、どうなんでしょうか。
>※エラー発生時、エクスプローラ上ではネットワークドライブに「X」表示がされて
いました。
エラーが出て、復帰処理をするのならば、エラーの詳細を調べるのが当然だと思
うのですが、調べましたか?
まさかOSのGUIでエラーを確認できているのに調べていないなどということは無い
ですよね?
またWNetGetLastErrorと言うAPIもあり、ネットワークでエラーが出ているのなら
ば真っ先に使うべきAPIだと思うのですが、その点についても言及されていないよう
です。
使ったのならその結果も併せて書いたほうが有効な回答が得られるでしょう。
使っていないのならエラー処理の仕方を根本から学んだほうがいいと思います
が。
ふと思ったんですが、ネットワークドライブを提供している側のOSが
サーバーライセンスでない場合、同時接続数として許されるのは5ユーザーとか
かなり少なかったと思います。なので同時部複数のユーザーがアクセスしてしまうと
アクセスできなかったりする事もあったと思います。
そういったネットワークを使うが故の制限と言うのが出てきてしまうのは
致し方ない話なのでそこまで考えに入れた対処が必要だと思いますね。
同時アクセス数の制限の場合はいくら接続しようとしても空きが出ない限り
無駄だと思いますし。
> サーバーライセンスでない場合、同時接続数として許されるのは5ユーザーとか
> かなり少なかったと思います。
XP Proで10ユーザ、XP Homeで5ユーザですね。
# クライアント用なのでまぁそんなものかと思いますが。
ネットワークドライブの接続以外の接続などもあれば、それも含んだ値のはずで、
しかも、キャッシュなどの関係か、接続を切ったからといって直に解放されるわけではないらしい。
# 正式な仕様は知らないですが…どこかで解放タイミングは公開してるのでしょうか>識者の方々
毎秒接続なんてやってたら確かにこいつに引っかかる可能性はありそう…?
サーバーはCAL数以上の接続できるのかな?