Hello everybody,
I have following problem: I'm using C# ftp methods to automate sending files to FTP servers. The program is constantly running, checking predefined directories. If it finds files in a directory, it is supposed to upload them to a defined ftp server. There are about 80 directories and most of the time the program has something to do. Everything works fine, except from the following scenario:
- The file is being uploaded.
- An error occurs while uploading: the remote host is down, the quota is exceeded or something similar.
- An attempt is made to upload the file once again and the error occurs once again.
An attempt is made to upload file for the third, fourth, ... time and then this line of code:
Stream requestStream = ftpRequest.GetRequestStream();
throws WebException with status: Undefined, and description: the time limit for this operation has been reached (or something similar - I had to translate this from polish). While this WebException is being thrown, ftp request to other servers (files from different directories) succeed, so it looks like there is only problem with connection to this one ftp server.
It all results in no further attempt to upload file being successful. Uploading this file through other ftp client is, however, possible. When I restart the program, everything runs smoothly. Should I somehow manually release ftp resource? I'm using KeepAlive property of FtpWebRequest set to true..
I would very appreciate if someone could shed some light on this problem.
Edited:
I followed David's hint and found the place where I didn't call Close() method on the requestStream, I fixed it, but the problem reoccurred.
I will paste some code then. Here is part of the method, that uploads the file to the server. If it fails, another attempt is being made, something like:
while (retryCounter++ < retryNumber)
{
//upload file,
//if succeeded, break
}
inside while-block there is:
FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(remoteFileName);
ftpRequest.UseBinary = true;
ftpRequest.UsePassive = true;
ftpRequest.Credentials = new NetworkCredential(UserName, Password);
ftpRequest.ReadWriteTimeout = SendTimeout;
ftpRequest.Timeout = ConnectTimeout;
ftpRequest.KeepAlive = true;
ftpRequest.Proxy = null;
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
Stream requestStream = null;
try
{
using (MemoryStream fileStream = new MemoryStream(localFile))
{
byte[] buffer = new byte[BufferSize];
int readCount = fileStream.Read(buffer, 0, BufferSize);
int bytesSentCounter = 0;
while (readCount > 0)
{
requestStream.Write(buffer, 0, readCount);
bytesSentCounter += readCount;
readCount = fileStream.Read(buffer, 0, BufferSize);
System.Threading.Thread.Sleep(100);
}
}
requestStream.Close();
requestStream = null;
FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse();
FtpStatusCode code = response.StatusCode;
string description = response.StatusDescription;
response.Close();
_logger.Information("Upload file result : status code {0}, status description {1}", code, description);
if (code == FtpStatusCode.ClosingData)
{
_logger.Information("File {0} uploaded successfully", localFileName);
}
else
{
_logger.Error("Uploading file {0} did not succeed. Status code is {1}, description {2}", localFileName, code, description);
}
}
catch (WebException ex)
{
if (requestStream != null)
requestStream.Close();
ftpRequest.Abort();
FtpStatusCode code = ((FtpWebResponse)ex.Response).StatusCode;
string description = ((FtpWebResponse)ex.Response).StatusDescription;
_logger.Error("A connection to the ftp server could not be established. Status code: {0}, description: {1} Exception: {2}. Retrying...", code, description, ex.ToString());
}
So, again the scenario is following:
1. The file is being uploaded and System.Net.Sockets.SocketException occurrs.
2. Another attempt is being made and System.Net.Sockets.SocketException reoccurs.
3. Always before I call the uploadfile method, I check whether the remote server is up and everything is ok by trying to list the remote directory. And from now, by calling
ftpRequest.GetResponse() (where ftpRequest.Method is WebRequestMethods.Ftp.ListDirectory) I get WebException with status: Undefined, and description: the time limit for this operation has been reached. When I restart the application, the problem disappears.
I can find no other place where the streams are not released properly, and have no idea what to do next..