tags:

views:

2109

answers:

4

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:

  1. The file is being uploaded.
  2. An error occurs while uploading: the remote host is down, the quota is exceeded or something similar.
  3. An attempt is made to upload the file once again and the error occurs once again.
  4. 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..

+1  A: 

Are you sure you're closing the stream correctly and thus release all underlying resources properly?

If not, this might be the cause of your problem, when you hit a limit (e.g. open sockets) after repeated failures.

David Schmitt
Well, I didn't call requestStream.Close() after the first error occurred in the catch(WebException) block.. Now I see this.. Could this be it, so simple? :)Thank you very much!
Agata
A: 

One possible source of error that I've run into is creating a new "NetworkCredential" over and over again. Then you'll get an exception after awhile.

danbystrom
I've read about this "Network Credential" problem, but I don't think this is a case here. I've got servers that have files uploaded every half hour, six days a week and the problem never occurred. It happens only in this particular scenario - when the first two attempts fail while uploading file. I think David figured it right. We'll see..
Agata
Well... I said "possible". :-) I had that problem myself in an app that worked similar to yours, and what's funny was that it was used for a long period transfering files to an IIS server with no problem. But when we started transfering files to a Unix server instead, then this error showed up!
danbystrom
A: 

You need to ensure you put the Stream.Close(), Request.Close() and Response.Close() in a finally block otherwise they will be skipped whenever there is an error. Keep in mind when dealing with external resources such as over a network, you need to program to expect errors since they will certainly crop up at some point.

try 
{ 
    processing here...
} 
finally
{
     requestStream.Close(); 
     requestStream = null;
}
NightOwl888
A: 

Another Free Fast Multi Site File Uploader: http://www.multisiteupload.com You can upload music, video, photos, images, files, pdf, zip… to 12 Hots with only one click in seconds. Works well. Recommended.

Ramonfer