我試圖移動到使用System.Net.FtpClient,但事情沒有按預期工作。System.Net.FtpClient.FileExists零星故障
運行下面的代碼,好像即使IsConnected
返回true,直接下調用FileExists()
電話Connect()
(這意味着連接丟失完全調用之間?)。但是,由於Connect()
可能會不時失敗,這也導致失敗FileExists()
(其中失敗意味着它會拋出Connection refused
)。
我的代碼有什麼問題嗎?這是否值得期待,即我是否應該準備重試我對FtpClient
實例所做的所有事情?是否有任何標誌設置爲自動重試?
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);
其中GetClient()的使用我的自定義「重試循環」,以喊得零星的連接失敗的實現。
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);
}
這是偶爾出現的異常:原來的FtpClient被重新連接
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
向我們顯示日誌文件('FtpTrace.AddListener')。 –