- PR -

FTP受信中にエラー

投稿者投稿内容
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-07-06 23:11
引用:

もし、他のメジャーなFTPツールでも起きるのならば
長時間つないでいると相手が出すエラーだから仕方ないんじゃない。



どのくらい困っているのかわかりませんが、
keepaliveしないようにすれば動くようですし、
仕方ない、と言えるならそれでいいですね。

HTTPWebRequestもFTPWebRequestも高位のクラスですからかなり癖があり、
ネットワークやサーバー環境によっては動かなくなります。
ですが、いろいろ設定する方法があり、
問題発生の状況によっては対応することができます。

相手が出すエラーでも対応する方法もありますし、
エラーが出ても接続を切らずにうまく切り抜ける方法もあります

それほど必死じゃないなら、
もうここに投稿せずにスルーすればOK。

どうしても何とかしなければならないなら、
状況を詳しく説明すれば、
私や誰かが解決する方法を知っているかもしれません、ね。
のん吉
会議室デビュー日: 2007/07/05
投稿数: 8
投稿日時: 2007-07-09 12:20
れいさん、こんにちは


引用:

伝わりませんでした。
私にはエラー発生の状況がまったく把握できていません。


申し訳ございませんでした。
長くなりますが、コード部分を書きます。

===== ループ部分 ======
date = 前回取得した日付;
do
{
string remote_path = "ftp://192.168.0.1/down/"
+ date.toString("yyyyMMdd") + "*.CSV";
string strbuf = GetDirectory(remote_path,"ftpid","ftppass");
string[] strFiles = strbuf.Replace("\r\n", "\n").Split('\n');
foreach (string s in strFiles)
{
if (s == "") break;
FtpDownload("ftp://192.168.0.1/down/" + s,
"c:\\down\\" + s,
"ftpid",
"ftppass");
}
date = date.AddDays(1);
} while (date <= DateTime.Today);

===== ディレクトリサーチ部分 ======
private string GetDirectory(string uri, string id, string pass)
{
string strDirectory = null;

FtpWebRequest req = (FtpWebRequest)WebRequest.Create(uri);
req.Credentials = new NetworkCredential(id,pass);
req.KeepAlive = false; // これを入れてエラーが出なくなりました
req.Method = WebRequestMethods.Ftp.ListDirectory;

FtpWebResponse res;
try
{
res = (FtpWebResponse)req.GetResponse();
}
catch (WebException ex)    //←←ここでエラーになります。
{
MessageBox.Show(ex.Message, ex.Status.ToString());
return "";
}

Stream resStream = null;
StreamReader reader = null;
try
{
resStream = res.GetResponseStream();
reader = new StreamReader(resStream,
System.Text.Encoding.GetEncoding("SHIFT_JIS"));
if (reader != null)
{
strDirectory = reader.ReadToEnd();
}
}
catch (WebException ex)
{
MessageBox.Show(ex.Message);
}
finally
{
res.Close();
reader.Close();
resStream.Close();
}
return strDirectory;
}

===== ダウンロード部分 ======
private bool FtpDownload(string uri, string localfile, string id, string pass)
{
FtpWebRequest req = (FtpWebRequest)WebRequest.Create(uri);
req.Credentials = new NetworkCredential(id, pass);
req.Method = WebRequestMethods.Ftp.DownloadFile;
FtpWebResponse res;
try
{
res = (FtpWebResponse)req.GetResponse();
}
catch (WebException ex)
{
MessageBox.Show(ex.Message + "\n" + localfile);
return false;
}
Stream resStream = null;
StreamReader reader = null;
StreamWriter writer = null;
try
{
resStream = res.GetResponseStream();
reader = new StreamReader(resStream,Encoding.GetEncoding("SHIFT-JIS"));
if (reader != null)
{
writer = new StreamWriter(localfile, false,
Encoding.GetEncoding("SHIFT-JIS"));
writer.Write(reader.ReadToEnd());
}
}
catch (WebException ex)
{
MessageBox.Show(ex.Message + "\n" + localfile);
return false;
}
finally
{
reader.Close();
res.Close();
writer.Close();
resStream.Close();
}
return true;
}

===== ここまで ======

引用:

ある日の処理が大量にあった場合、
次の日のファイル情報を取得しているときにエラーがでるということですか?
それともある日の処理が大量にあった場合、
その日のファイル情報取得でエラーがでるのですか?


ある日付のファイル量には関係なく、
読み込む日付の期間が長いと途中のディレクトリサーチ時点でエラーになります。

引用:

引用:

試しに、エラーになったファイルだけを指定するとエラーは表示されません。


ディレクトリ情報取得中にエラーが起きるのでしたら、
エラーになったファイルというのは何のことでしょうか?


書き方が悪くて申し訳ありません。
エラーになった日付指定で1回だけの処理で読むとエラーにならないです。

また、FTPツール(FFFTP)で試すと、エラーにはなりません。

エラー的には、keepaliveで出なくなったのですが、
根本的な理由が分からない為、このまま利用していいのか
迷っております。

れいさん、皆さん
どうかアドバイスをよろしくお願いします。


[ メッセージ編集済み 編集者: のん吉 編集日時 2007-07-09 12:21 ]
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-07-09 13:43

おそらくは認証の問題です。
接続先サーバーもネットワーク構成もわかりませんので、
確実にこれで治ります、とは言えませんが、
少なくともNetworkCredentialの使い方が間違っています。

FTPWebRequestやHTTPWebRequestは、
NetworkCredentialを毎回初期化して用いると、
前回の要求時のCredentialを忘れてしまう場合があります。

その場合、以前の要求で用いたのと同じユーザー名でも再認証を試みます。
HTTPの場合は要求志向なのであまり問題ありませんが、
FTPは接続ごとに認証を管理しているので、
再認証を試みるとエラーになります。

ループ開始時にNetworkCredentialインスタンスを一つ作成し、
それをすべてのFTPWebRequestで共有するようにするのが正しい方法です。

それでだめな場合は…
パケットキャプチャしないと私にはわかりません。
のん吉
会議室デビュー日: 2007/07/05
投稿数: 8
投稿日時: 2007-07-09 14:36
れいさん
うまく動作致しました、ありがとうございます。

れいさんのおっしゃるとおり、認証の部分を
引用:

ループ開始時にNetworkCredentialインスタンスを一つ作成し、
それをすべてのFTPWebRequestで共有するようにするのが正しい方法です。


で、実行したところ問題が解決しました。


引用:

FTPWebRequestやHTTPWebRequestは、
NetworkCredentialを毎回初期化して用いると、
前回の要求時のCredentialを忘れてしまう場合があります。

その場合、以前の要求で用いたのと同じユーザー名でも再認証を試みます。
HTTPの場合は要求志向なのであまり問題ありませんが、
FTPは接続ごとに認証を管理しているので、
再認証を試みるとエラーになります。



大変、参考になりました。
しかし、このような情報はどうやって調べているのでしょうか?
結構、調べたつもりでしたが。。。

皆さん、本当にありがとうございました。
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-07-09 15:40
>しかし、このような情報はどうやって調べているのでしょうか?
>結構、調べたつもりでしたが。。。

えーっと。

調べるというのはWebやMSDNですか?
あれこれコーディングはしましたか?

今回の件は、以前WebRequestについて調べた際、
私が実際にコーディングしてあれこれ試したときの知識です。
誰にも言ってませんし、Webに載せてもいないので、
Webに載っていなくてもおかしくはありません。

FTPの仕組みとWebRequestの仕組みをよく理解して、
コーディングしてパケットキャプチャすれば
今回の問題は調べられます。
それほど難しくはありません。

ご参考までに、
問題が発生した場合の
私の処理アルゴリズムを載せておきます。

コード:
do {
  do {
    google(日本語)
    MSDN(日本語)
    google(英語)
    MSDN(英語)
  } while (!腹減り && !理解 )
  コーディング
  紅茶
} while (!腹減り && !解決)



無限ループにならないように
腹減りタイマーで処理時間を計測する必要があります。
のん吉
会議室デビュー日: 2007/07/05
投稿数: 8
投稿日時: 2007-07-09 16:16
れいさん、ありがとうございます。

まだまだ、初心者なので調べ方を調べるのに
時間を費やしている段階です。。。

今の所、Web(日本語)とMSDNで調べながら
コーディングして動作確認程度で、WebRequestの仕組み
まで手が出ていませんでいた。
それなのに、調べたつもりなんて言ってしまいました。。。

今後は、れいさんのアルゴリズムを参考に
無限ループに陥ったら、書き込みさせて頂きます。
(英語はわかりませんが。。。)

れいさん、本当にありがとうございました。

スキルアップ/キャリアアップ(JOB@IT)