Загрузка файла с использованием методов c # ftp приводит к исключению webexception. Проблема исчезает после перезапуска программы - PullRequest
2 голосов
/ 08 мая 2009

У меня следующая проблема: Я использую методы C # ftp для автоматизации отправки файлов на FTP-серверы. Программа постоянно работает, проверяя предопределенные каталоги. Если он находит файлы в каталоге, он должен загрузить их на определенный FTP-сервер. Существует около 80 каталогов, и в большинстве случаев программе есть чем заняться. Все отлично работает, кроме следующего сценария:

  1. Файл загружается.
  2. Ошибка при загрузке: удаленный хост отключен, квота превышена или что-то подобное.
  3. Предпринята попытка загрузить файл еще раз, и ошибка повторяется.
  4. Предпринята попытка загрузить файл на третий, четвертый, ... раз, а затем эту строку кода:

    Поток requestStream = ftpRequest.GetRequestStream ();

выдает WebException со статусом: Undefined и description: срок для этой операции достигнут (или что-то подобное - мне пришлось перевести это с польского). Пока создается это исключение WebException, запрос ftp на другие серверы (файлы из разных каталогов) выполняется успешно, поэтому похоже, что существует проблема только с подключением к этому одному серверу ftp.

Все это приводит к тому, что дальнейшая попытка загрузки файла не удалась. Однако выгрузка этого файла через другой ftp-клиент возможна. Когда я перезапускаю программу, все работает без сбоев. Должен ли я как-то вручную освободить ресурс ftp? Я использую свойство KeepAlive для FtpWebRequest со значением true ..

Буду очень признателен, если кто-нибудь сможет пролить свет на эту проблему.

Отредактировано:

Я последовал совету Дэвида и нашел место, где не вызывал метод Close () для requestStream, я исправил его, но проблема снова возникла.

Тогда я вставлю код. Вот часть метода, который загружает файл на сервер. Если это не удается, делается другая попытка, что-то вроде:

while (retryCounter++ < retryNumber)
{
  //upload file,
  //if succeeded, break
}

внутри блока while:

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());

}

Итак, снова сценарий следующий:
1. Файл загружается и возникает исключение System.Net.Sockets.SocketException.
2. Еще одна попытка, и System.Net.Sockets.SocketException повторяется.
3. Всегда перед вызовом метода uploadfile я проверяю, работает ли удаленный сервер и все ли в порядке, пытаясь составить список удаленных каталогов. И с этого момента, позвонив ftpRequest.GetResponse () (где ftpRequest.Method - WebRequestMethods.Ftp.ListDirectory) Я получаю исключение WebException со статусом: Undefined и description: ограничение по времени для этой операции достигнуто. Когда я перезапускаю приложение, проблема исчезает.

Я не могу найти другого места, где потоки не освобождаются должным образом, и не знаю, что делать дальше ..

Ответы [ 3 ]

1 голос
/ 06 марта 2010

Необходимо убедиться, что вы поместили Stream.Close (), Request.Close () и Response.Close () в блок finally, в противном случае они будут пропущены при возникновении ошибки. Имейте в виду, что при работе с внешними ресурсами, такими как по сети, вам необходимо запрограммировать на ожидание ошибок, так как они обязательно возникнут в какой-то момент.

try 
{ 
    processing here...
} 
finally
{
     requestStream.Close(); 
     requestStream = null;
}
1 голос
/ 08 мая 2009

Вы уверены, что правильно закрываете поток и, таким образом, правильно высвобождаете все базовые ресурсы?

Если нет, это может быть причиной вашей проблемы, когда вы достигнете предела (например, открытых сокетов) после повторных сбоев.

0 голосов
/ 08 мая 2009

Одним из возможных источников ошибок, с которыми я столкнулся, является создание нового «NetworkCredential» снова и снова. Через некоторое время вы получите исключение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...