ファイル転送中(Inet)に処理がフリーズしないには?


ヨリ子  2005-04-04 07:32:44  No: 89190

[OSのVER]:Windows 2000
[VBのVER]:VB 6.0

こんばんは。初めて投稿させていただきます(*^。^*)
現在、複数のUNIX上に存在するファイルをCSに転送したいと考えているのですが、
いくつかのファイルを転送した後に、StateChangedイベント内で
処理が止まってしまう感じになってしまっています。。。
(転送するファイルのサイズが関係しているのかと思いましたが、そうとも言えないようで・・・)
以下がソースの一部です。
(ソース自体が会社のPCにしかないので、かなり省略してしまっています・・・ごめんなさい)

=========================================================
' UNIXサーバ接続が完了しているのを前提で↓

Inet1.Excecue "Get ---- ""
Do While Inet1.StillExcecuting
   Do Events
Loop

≪StateChangedイベント内≫

Select Case State
    Case icError  ' エラー発生時
    ' --- エラー処理 ---
End Select
=========================================================

最終的には、エラー番号12002、タイムアウトで落ちてしまいます・・・
そこで、現在、以下の2つの方法を検討しています。

① StateChangedイベント内の処理を変えて、
   Excecueプロパティ実行後、フラグを監視するようにする。
   (こんな感じでしょうか?↓)

Do While blnSyoriFlg = False
    Select Case State
    Case icRequestCompleted
        blnSyoriFlg = True
    Case icError
    ' --- エラー処理 ---
    End Select
Loop

② 使用するコントロール自体を変える。
   Inetコントロールから、Winsock、またはAPIに変更する。
   その際、以下の3処理が行えることが前提。。。

・UNIX上に転送するファイルと同名のファイルが存在する場合、ファイルを削除する。
・ファイルを転送する。  
・UNIXに転送したファイルのサイズを取得する。

以上の2つの方法で、何かアドバイスをいただけないでしょうか?
この2つよりもっといい方法があれば教えて欲しいかもです。。。
お願いします(>_<)


ねろ  2005-04-04 18:59:00  No: 89191

サーバーからの応答が返ってこないことは結構有ることなので、
タイムアウトを短く設定しておいて、タイムアウトが発生したら
再度、未処理の項目から処理を開始すれば良いような気がしますが。


ヨリ子  2005-04-04 22:09:21  No: 89192

ねろさん、回答ありがとうございます。

>> タイムアウトを短く設定しておいて、タイムアウトが発生したら
>> 再度、未処理の項目から処理を開始すれば良いような気がしますが。

これは、RequestTimeoutプロパティをGet(Put)プロパティを行う前に設定して、
StateChangedイベント内でタイムアウトによるエラーが発生した際に、再度Getプロパティを行うということでしょうか?

ちなみに、ファイルのサイズが500MBくらいある場合、転送処理に6分ちょっとかかっていた気がします。。。
ファイルのサイズを考えると、6分以上の値を設定しておく必要があるのでしょうか・・・?


ねろ  2005-04-04 23:18:28  No: 89193

>>ファイルのサイズを考えると、6分以上の値を設定しておく必要があるのでしょうか・・・?
MSDNによるとRequestTimeoutの指定時間は、
>>Execute メソッドで送信した要求への応答が指定時間内に返されなかった場合は、
>>StateChanged イベントが発生し、エラー コードが返されます。
となっています。ダウンロードしている時は、応答していると思いますが。


ヨリ子  2005-04-05 00:09:13  No: 89194

ねろさん、度々ありがとうございます(/_;)

>>Execute メソッドで送信した要求への応答が指定時間内に返されなかった場合は、
>>StateChanged イベントが発生し、エラー コードが返されます。

ということは、ダウンロード中はサーバが応答している状態なので、
タイムアウトに設定した時間には影響しないんですね。
そうすると、以下のソースで問題ないでしょうか・・・?

Dim strInetFlg    As String

Grt_Proc:
Inet1.RequestTimeout = 60        ' タイムアウト時間を60秒に設定
Inet1.Excecue "Get --- 省略 --- "

If strInetFlg = "1" Then         ' タイムアウトした場合、再度処理を実行(Get_Procへ移動)
    Goto Get_Proc                
Elseif strInetFlg = "9" Then     ' エラーが発生した場合、サーバとの通信を切断する
    Inet1.Excecue "Close"
    Inet1.Excecue "Quit"
End If

Private Sub StateChanged()
    Dim blnInetFlg    As Boolean
    blnInetFlg = False  

    Do
      Select Case State
      Case icRequestCompleted
            blnInetFlg = True
            strInetFlg = "0"        ' 正常に処理を終了
      Case icError
      If Inet1.Responsecode = "(タイムアウトの場合)" Then
                blnInetFlg = True
                strInetFlg = "1"    ' タイムアウトによる処理の終了
       Else
                blnInetFlg = True
                strInetFlg = "9"    ' エラーにて処理を終了
            End If
         End Select
    Loop Until blnInetFlg

End Sub


ヨリ子  2005-04-05 00:11:42  No: 89195

>> Grt_Proc:
>> Inet1.RequestTimeout = 60        ' タイムアウト時間を60秒に設定
>> Inet1.Excecue "Get --- 省略 --- "

すいません、、、"Grt_Proc"ではなく、"Get_Proc"の間違いです。。。


ガッ  2005-04-05 00:51:49  No: 89196

※横スマソ;
ソースみて少し気になったんだけど、
> Private Sub StateChanged()
の内部で、無限ループに陥る可能性とかは、絶対に無いの?


LESIA  2005-04-05 02:28:21  No: 89197

>>>Execute メソッドで送信した要求への応答が指定時間内に返されなかった場合は、
>>>StateChanged イベントが発生し、エラー コードが返されます。
>
>ということは、ダウンロード中はサーバが応答している状態なので、
>タイムアウトに設定した時間には影響しないんですね。

いや、だから
>ファイルのサイズを考えると、6分以上の値を設定しておく必要があるのでしょうか・・・?
必要があるということです。

Inet1.RequestTimeout = 600        ' タイムアウト時間を10分に設定
Inet1.Excecue "Get --- 省略 --- "

Private Sub StateChanged()
    Select Case State
    Case icRequestCompleted
        ' 正常に処理を終了
    Case icError
        ' エラーにて処理を終了
    End Select
End Sub


LESIA  2005-04-05 02:40:52  No: 89198

ちょっと補足
>ということは、ダウンロード中はサーバが応答している状態なので、
>タイムアウトに設定した時間には影響しないんですね。
ダウンロード中は、例え6分以上掛かっていても正常にサーバーが応答しているので
もしタイムアウトが60秒だと、正常にサーバーが応答しているにも関わらず、
StateChangedイベントが発生し、エラーコードが返されてしまいす。
しかし、タイムアウトを6分以上にしておけば、ダウンロードが完了するまで
StateChangedイベントは発生せず、よけいなコードを書かなくてすむというわけです。


ヨリ子  2005-04-05 03:05:44  No: 89199

ガッさん、LESIAさん、本当にありがとうございます。

>> Execute メソッドで送信した要求への応答が指定時間内に返されなかった場合は、
>> StateChanged イベントが発生し、エラー コードが返されます。
>  もしタイムアウトが60秒だと、正常にサーバーが応答しているにも関わらず、.
>  StateChangedイベントが発生し、エラーコードが返されてしまいす。

要求への応答とは、あくまで“正常に転送処理を終了した”という応答なんですね。
ということは、転送処理が終了するまでにタイムアウト時間を過ぎるとエラーで返ってきてしまうんですね。

転送処理にどのくらい時間がかかるか分からない場合は、下手にタイムアウト時間を
設定しない方がいいのかもしれませんね。

>> Private Sub StateChanged()
>> の内部で、無限ループに陥る可能性とかは、絶対に無いの?

最終的には必ずicErrorかicRequestCompletedでコードが返されると思っていたのですが、
そうではないんですかね・・・?
実行するプロパティによって変化するのかな。。。

以下のソースですと、処理結果を監視する部分がないように思うのですが、
StateChangedイベント内、またはGetプロパティ実行後にループで処理結果を
監視する必要はないのでしょうか・・・?

Dim blnInetFlg    As Boolean

Inet1.RequestTimeout = 600        ' タイムアウト時間を10分に設定
Inet1.Excecue "Get --- 省略 --- "

Private Sub StateChanged()
    Select Case State
    Case icRequestCompleted    ' 正常に処理を終了
        blnInetFlg = True
    Case icError               ' エラーにて処理を終了
        blnInetFlg = False
    End Select
End Sub


ねろ  2005-04-05 06:53:55  No: 89200

あれ!
>Private Sub StateChanged()

Private Sub Inet1_StateChanged(ByVal state As Integer)
かな。

>以下のソースですと、処理結果を監視する部分がないように思うのですが、
StateChangedは割り込みで、その処理が行われると呼び出される為監視の
必要はありません。

>最終的には必ずicErrorかicRequestCompletedでコードが返されると思っていたのですが、
>そうではないんですかね・・・?
私もそう思います、従って無限ループにはならないかな、ただし上記の理由でDo〜Loopに
する必要は無いと思われます。

最初の質問に戻って、ホストの応答が無くフリーズした様になり、タイムアウトが発生
した場合、一度接続を切り再接続、処理の続行をしたらいかがですか。
ホストによってエラーは様々なのですが、StateChangeでログを書き出したら、どこで
ハングするか判る可能性は有ります。

タイムアウトは  Inet1.RequestTimeout =  0とすると無限大に設定されます。
アップロードの場合はファイルサイズから大体の時間はわかりますから、
およそのタイムアウトの時間をセットした方が良いのではないかと思います。

Inetコントロールは色々な制限事項がありうまくいかない場合は、WinInet.Dllの
FtpPutFileやFtpCommand等を使用する、DosのFtpコマンドを使用する、その他の
Dllを使用するなどの方向転換が必要になります。
そろそろ帰って寝よ。。。


ヨリ子  2005-04-05 07:37:36  No: 89201

お忙しいところ返信ありがとうございます。
ねろさんのご意見より考えてみましたところ、
以下のようなソースでタイムアウト時に再処理が行えるのではないかと
思うのですが、いかがでしょうか・・・?

Dim blnInetFlg    As Boolean
Dim strErrFlg     As String    ' 正常終了時:0  エラー終了:1  タイムアウト:2

blnInetFlg = False
Inet1.RequestTimeout = 600     ' タイムアウト時間を10分に設定
Inet1.Excecue "Get --- 省略 --- "
Do While blnInetFlg = False
    Do Events
Loop 

If strErrFlg = "2" Then
    ' 一旦切断し、続きから処理を続行
Elseif strErrFlg = "1" Then
    ' エラー処理
End If

Private Sub Inet1_StateChanged(ByVal state As Integer)
    Select Case State
    Case icRequestCompleted    ' 正常に処理を終了
        blnInetFlg = True
        strErrFlg = "0"
    Case icError               ' エラーにて処理を終了
        '// タイムアウトにてエラーが発生した場合
        if Inet1.Responsecode = "12002"
            blnInetFlg = True
            strErrFlg = "2"
        Else
            blnInetFlg = True
            strErrFlg = "1"
        End If
    End Select
End Sub

ちなみに、APIやDosのFTPコマンドを使用した場合は、
タイムアウト時の処理などを考えなくて良いのでしょうか?
それなら方向転換した方がいいのかな、って思いました。。。(^_^;)


ガッ  2005-04-05 08:26:24  No: 89202

※実験してみましたw
StateChangedイベントの挙動について
1  ExecuteメソッドでHTTPサーバにGETメソッドを送信する(適当なFTP見つからなかったです(orz
2  StateChangedイベントで、
    icResolvingHost→icHostResolved→icConnecting→icResponseCompleted
    と発生。
まぁ、イベントは色々起こるみたいです。

で、InetコントロールのRequestTimeoutの挙動について。
1  [Inet].RequestTimeoutに3を代入
2  Executeメソッドでありえないサーバ(http://hoge)に
    GETメソッドを送信する
3  "リモートホストに接続できません"エラー発生(orz
−タイムアウトが発生しないので実験中断−

ノ<ところで、MSDNのRequestTimeoutには「エラーが発生します」と書いてあるんだよねぇ…
まぁ、発生するのでしょうから、StateChangedイベントで得るものではなく、
On Error ステートメントで例外をキャッチしないといけないかもしれません。
※情報は不正確の場合があります。
環境:WinXP(Home)SP2、VB6(SP6)、MSINET.OCX(FileVersion 6.01.9782)


ねろ  2005-04-05 17:41:04  No: 89203

ヨリ子さん
長い間CPUの使用率が100%に張り付くので、
Do While blnInetFlg = False
    Do Events
    Sleep(1)
Loop 
方がGoodかも。(Sleep()はAPI)

>ちなみに、APIやDosのFTPコマンドを使用した場合は、
>タイムアウト時の処理などを考えなくて良いのでしょうか?
WinInet.Dllの場合
    1、非データの送信要求のタイムアウト時間
    2、非データの受信要求のタイムアウト時間
    3、データの送信要求のタイムアウト時間
    4、データの受信要求のタイムアウト時間
の4つのタイムアウトが設定できます。(^^;
ただし、たとえば4番ですがこれを5秒に設定しても、3〜4分ダウンロードにかかる
ファイルでも、ダウンロード中にタイムアウトすることは無いようです。
私の環境も『ガッさん』と同じで、Inetダウンローロ出来ません、従ってInetのタイムアウトがどのように
なっているかはわかりません。
この辺は逆に『ヨリ子さん』にタイムアウトを10秒位に設定して、大きなファイルを
ダウンロードした場合タイムアウトが発生するか否かちょっとやってみてほしいような気がします。
まあいずれにしろタイムアウトを使いたくない場合は設定しなければ良いだけです。
Ftpの場合サーバーとクライアントの組み合わせで一概にこうだとは言いにくく
やってみて出来たらOKと言うことが多いようです。

ガッさん
RequestTimeoutの説明でMSDNには
>「エラーが発生します」
はあくまでも『OpenURL メソッド (同期処理) で要求を送信した場合』で
『Execute メソッドで送信した要求への応答が指定時間内に返されなかった場合は、
StateChanged イベントが発生し、エラー コードが返されます。』
となっていますので、StateChanged のイベント待ちでいいと思います。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加