I was having an issue with random disconnections with some code I put together. This code was creating a new FTP session with the "Using" command which meant the session was disposed after every transfer.
I noticed that around 1-2 mins after the original session was disposed, I would get disconnected on the next transfer. I decided this was the wrong way to do things anyway and rewrote it to use a single session for everything.
This has worked fine, but now I wanted to implement something so that if a transfer failed for some reason, we would dispose the whole thing, and create a new session and try again. I'm back to the same issue that the dispose seems to cause the next transfer to be killed about 70 seconds in. I can and have mitigated this, by delaying any subsequent transfers by 2 minutes and this has worked around the issue. This is clearly far from ideal. What is happening with the session.dispose that causes the next transfer to fail about 70 seconds in?
static public void DownloadThread(string IPAdd, int ThreadNum)
{
Session session;
session = OpenSession(IPAdd, ThreadNum);
//Kick out if the session isn't opened.
if (!session.Opened)
{
Log("Unable to Connect to " + IPAdd, ThreadNum);
abortThread(ThreadNum);
}
Log("Sending file to IP: " + IPAdd, ThreadNum);
string filename = Path.GetFileName(Globals.FileToSend);
string result = FTPSendFile(IPAdd, Globals.FileToSend, Globals.RemoteLocation, ThreadNum, filename, session);
if (result.Contains("226"))
{
Log("File upload completed and verified!", ThreadNum);
}
else
{
Log("File upload Failed! Killing thread.", ThreadNum);
abortThread(ThreadNum);
}
session.Dispose();
}
private static Session OpenSession(string IP, int ThreadNum)
{
// Setup session options
SessionOptions sessionOptions = new SessionOptions
{
Protocol = Protocol.Ftp,
HostName = IP,
UserName = "anonymous",
Password = "anonymous@example.com",
TimeoutInMilliseconds = 3600000
};
Session session = new Session();
session.FileTransferProgress += (sender, e) => SessionFileTransferProgress(sender, e, ThreadNum);
session.Open(sessionOptions);
return session;
}
static public string FTPSendFile(string IP, string LocalFile, string remoteFileLocation, int ThreadNum, string FinalFileName, Session session)
{
currentFileUploading = FinalFileName;
string fullRemoteFileName = remoteFileLocation + FinalFileName;
int RetryAttempts = 3;
while (RetryAttempts > 0)
{
TransferOptions transferOptions = new TransferOptions();
transferOptions.TransferMode = TransferMode.Binary;
try
{
TransferOperationResult transferResult;
transferResult = session.PutFiles(LocalFile, fullRemoteFileName, false, transferOptions);
transferResult.Check(); //Triggers the execption
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine("Upload of {0} logged as failure, due to {1}", LocalFile, e);
}
//Check does remote file match local file.
long RemoteFilesizeBytes = session.GetFileInfo(fullRemoteFileName).Length;
//Get local file size
FileInfo fileInfo = new FileInfo(LocalFile);
long LocalFileSize = fileInfo.Length;
if (RemoteFilesizeBytes == LocalFileSize)
{
return "226";
}
//If we get here something went wrong.
session.Dispose();
if (RetryAttempts > 1)
{
Log("Error during download, " + RetryAttempts.ToString() + " retries left.", ThreadNum);
}
else if(RetryAttempts == 1)
{
Log("Error during download, " + RetryAttempts.ToString() + " retry left.", ThreadNum);
}
else
{
Log("Error during download, no retries remain. Abort",ThreadNum);
}
Thread.Sleep(30000);
session = OpenSession(IP,ThreadNum);
//Kick out if the session isn't opened.
if (!session.Opened)
{
Log("Abort: unable to reconnect to " + IP, ThreadNum);
abortThread(ThreadNum);
}
}
return "Error: Download failed, out of retries.";
}