2016-11-07 25 views
0

私はSystem.Net.FtpClientの使用に移行しようとしていますが、期待通りに機能しません。以下のコードを実行System.Net.FtpClient.FileExistsの散発的な失敗

、それは本当にもかかわらずIsConnected戻り、FileExists()通話Connect()に直接次の呼び出しのように思える(接続が正確に呼び出しの間に失われることを意味します?)。しかし、Connect()が毎回失敗する可能性があるので、これもまた失敗しますFileExists()(ここで失敗すると、Connection refusedがスローされます)。

私のコードに問題はありますか?これは予期されるものですか?つまり、FtpClientインスタンスで行うすべての操作を再試行する必要がありますか?自動的に再試行するように設定するフラグはありますか? GetClient()が散発的な接続障害をhandeために私のカスタム「リトライ・ループ」を使用して実装されて

string myPath = ..; 
string myTempPath = myPath+".tmp"; 

_client = GetClient(_ioc, false); 
var _stream = _client.OpenWrite(myTempPath); 

//write to stream 

_stream.Close(); 
Android.Util.Log.Debug("NETFTP", "connected: " + _client.IsConnected.ToString()); //always outputs true 

if (_client.FileExists(myPath) //sporadically throws, see below 
    _client.DeleteFile(myPath); 

private static T DoInRetryLoop<T>(Func<T> func) 
{ 
    double timeout = 30.0; 
    double timePerRequest = 1.0; 
    var startTime = DateTime.Now; 
    while (true) 
    { 
     var attemptStartTime = DateTime.Now; 
     try 
     { 
      return func(); 
     } 
     catch (System.Net.Sockets.SocketException e) 
     { 
      if ((e.ErrorCode != 10061) || (DateTime.Now > startTime.AddSeconds(timeout))) 
      { 
       throw; 
      } 
      double secondsSinceAttemptStart = (DateTime.Now - attemptStartTime).TotalSeconds; 
      if (secondsSinceAttemptStart < timePerRequest) 
      { 
       Thread.Sleep(TimeSpan.FromSeconds(timePerRequest - secondsSinceAttemptStart)); 
      } 
     } 
    }  
} 

internal FtpClient GetClient(IOConnectionInfo ioc) 
{ 
    FtpClient client = new FtpClient(); 
    if ((ioc.UserName.Length > 0) || (ioc.Password.Length > 0)) 
     client.Credentials = new NetworkCredential(ioc.UserName, ioc.Password); 
    else 
     client.Credentials = new NetworkCredential("anonymous", ""); 

    Uri uri = IocPathToUri(ioc.Path); 
    client.Host = uri.Host; 
    if (!uri.IsDefaultPort) 
     client.Port = uri.Port; 
    client.EnableThreadSafeDataConnections = false; 

    client.EncryptionMode = ConnectionSettings.FromIoc(ioc).EncryptionMode; 

    Func<FtpClient> connect =() => 
    { 
     client.Connect(); 
     return client; 
    }; 
    return DoInRetryLoop(connect); 

} 

これは散発的に表示された例外です:

System.Net.Sockets.SocketException : Connection refused 
10-24 13:08:07.487 I/mono-stdout(24073):   at System.Net.Sockets.SocketAsyncResult.CheckIfThrowDelayedException() [0x00017] in /Users/builder/data/lanes/3540/1cf254db/source/mono/mcs/class/System/System.Net.Sockets/SocketAsyncResult.cs:127 
      at System.Net.Sockets.SocketAsyncResult.CheckIfThrowDelayedException() [0x00017] in /Users/builder/data/lanes/3540/1cf254db/source/mono/mcs/class/System/System.Net.Sockets/SocketAsyncResult.cs:127 
10-24 13:08:07.487 I/mono-stdout(24073):   at System.Net.Sockets.Socket.EndConnect (IAsyncResult result) [0x0002f] in /Users/builder/data/lanes/3540/1cf254db/source/mono/mcs/class/System/System.Net.Sockets/Socket.cs:1593 
      at System.Net.Sockets.Socket.EndConnect (IAsyncResult result) [0x0002f] in /Users/builder/data/lanes/3540/1cf254db/source/mono/mcs/class/System/System.Net.Sockets/Socket.cs:1593 
      at System.Net.FtpClient.FtpSocketStream.Connect (System.String host, Int32 port, FtpIpVersion ipVersions) [0x0011a] in [my source folder]src 
etftpandroid\System.Net.FtpClient\FtpSocketStream.cs:611 
10-24 13:08:07.487 I/mono-stdout(24073):   at System.Net.FtpClient.FtpSocketStream.Connect (System.String host, Int32 port, FtpIpVersion ipVersions) [0x0011a] in [my source folder]src 
etftpandroid\System.Net.FtpClient\FtpSocketStream.cs:611 
10-24 13:08:07.487 I/mono-stdout(24073):   at (wrapper remoting-invoke-with-check) System.Net.FtpClient.FtpSocketStream:Connect (string,int,System.Net.FtpClient.FtpIpVersion) 
      at (wrapper remoting-invoke-with-check) System.Net.FtpClient.FtpSocketStream:Connect (string,int,System.Net.FtpClient.FtpIpVersion) 
10-24 13:08:07.487 I/mono-stdout(24073):   at System.Net.FtpClient.FtpClient.Connect() [0x000ce] in [my source folder]src 
etftpandroid\System.Net.FtpClient\FtpClient.cs:807 
      at System.Net.FtpClient.FtpClient.Connect() [0x000ce] in [my source folder]src 
etftpandroid\System.Net.FtpClient\FtpClient.cs:807 
      at System.Net.FtpClient.FtpClient.Execute (System.String command) [0x00136] in [my source folder]src 
etftpandroid\System.Net.FtpClient\FtpClient.cs:735 
10-24 13:08:07.487 I/mono-stdout(24073):   at System.Net.FtpClient.FtpClient.Execute (System.String command) [0x00136] in [my source folder]src 
etftpandroid\System.Net.FtpClient\FtpClient.cs:735 
10-24 13:08:07.487 I/mono-stdout(24073):   at System.Net.FtpClient.FtpClient.Execute (System.String command, System.Object[] args) [0x00001] in [my source folder]src 
etftpandroid\System.Net.FtpClient\FtpClient.cs:694 
      at System.Net.FtpClient.FtpClient.Execute (System.String command, System.Object[] args) [0x00001] in [my source folder]src 
etftpandroid\System.Net.FtpClient\FtpClient.cs:694 
10-24 13:08:07.487 I/mono-stdout(24073):   at System.Net.FtpClient.FtpClient.DirectoryExists (System.String path) [0x0005d] in [my source folder]src 
etftpandroid\System.Net.FtpClient\FtpClient.cs:2679 
      at System.Net.FtpClient.FtpClient.DirectoryExists (System.String path) [0x0005d] in [my source folder]src 
etftpandroid\System.Net.FtpClient\FtpClient.cs:2679 
10-24 13:08:07.487 I/mono-stdout(24073):   at System.Net.FtpClient.FtpClient.FileExists (System.String path, FtpListOption options) [0x0001c] in [my source folder]src 
etftpandroid\System.Net.FtpClient\FtpClient.cs:2751 
10-24 13:08:07.487 I/mono-stdout(24073):   at System.Net.FtpClient.FtpClient.FileExists (System.String path) [0x00001] in [my source folder]src 
etftpandroid\System.Net.FtpClient\FtpClient.cs:2733 
      at System.Net.FtpClient.FtpClient.FileExists (System.String path, FtpListOption options) [0x0001c] in [my source folder]src 
etftpandroid\System.Net.FtpClient\FtpClient.cs:2751 
      at System.Net.FtpClient.FtpClient.FileExists (System.String path) [0x00001] in [my source folder]src 
etftpandroid\System.Net.FtpClient\FtpClient.cs:2733 
+0

ログファイル( 'FtpTrace.AddListener')を表示します。 –

答えて

1

それはFtpClientがあるため、「古いデータ」の再接続をトリガし、クライアントからのいくつかの予期しない応答による再接続されたことが判明しました。私の解決策は、質問に投稿されたDoInRetryLoopを使用してConnect()メソッドをオーバーライドするFtpClientから自分のクラスを派生させることでした。

これは、EnableThreadSafeDataConnections = falseまたは「CloneConnection」メソッドのオーバーライドでのみ機能します。後者はそれを仮想化する必要がありました。

関連する問題