2009-05-08 6 views
2

J'ai le problème suivant: J'utilise les méthodes ftp C# pour automatiser l'envoi de fichiers vers des serveurs FTP. Le programme est constamment en cours d'exécution, en vérifiant les répertoires prédéfinis. S'il trouve des fichiers dans un répertoire, il est supposé les télécharger sur un serveur ftp défini. Il y a environ 80 annuaires et la plupart du temps le programme a quelque chose à faire. Tout fonctionne correctement, sauf dans le scénario suivant:Le téléchargement d'un fichier avec les méthodes ftp c aboutit à une exception web. Le problème disparaît après le redémarrage du programme

  1. Le fichier est en cours de téléchargement.
  2. Une erreur se produit lors du téléchargement: l'hôte distant est en panne, le quota est dépassé ou quelque chose de similaire.
  3. Une tentative est effectuée pour télécharger à nouveau le fichier et l'erreur se produit à nouveau.
  4. Une tentative de télécharger le fichier pour la troisième, quatrième, ... le temps et cette ligne de code:

    flux requestStream = ftpRequest.GetRequestStream();

lancers francs WebException avec le statut: Non défini et description: la limite de temps pour cette opération a été atteint (ou quelque chose de similaire - je devais traduire du polonais). Pendant que cette exception WebException est lancée, la requête ftp vers d'autres serveurs (fichiers de différents répertoires) réussit, il semble donc qu'il y ait seulement un problème de connexion à ce serveur ftp.

Tout cela n'aboutit à aucune tentative de téléchargement de fichier en cours. Le téléchargement de ce fichier via un autre client FTP est cependant possible. Quand je redémarre le programme, tout se passe bien. Devrais-je libérer manuellement une ressource ftp? J'utilise KeepAlive propriété de FtpWebRequest mis à vrai ..

Je serais très reconnaissant si quelqu'un pouvait faire la lumière sur ce problème.

Modifié:

J'ai suivi indice de David et a trouvé l'endroit où je ne l'ai pas appeler la méthode Close() sur le requestStream, je l'ai fixé, mais le problème est réapparu.

Je vais coller du code puis. Voici une partie de la méthode, qui télécharge le fichier sur le serveur. Si elle échoue, une nouvelle tentative est faite, quelque chose comme:

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

à l'intérieur tout en bloc il y a:

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

}

Donc, encore une fois le scénario est le suivant:
1 Le fichier est en cours de téléchargement et les occurrences System.Net.Sockets.SocketException.
2. Une autre tentative est en cours et System.Net.Sockets.SocketException se produit à nouveau.
3. Toujours avant d'appeler la méthode uploadfile, je vérifie si le serveur distant est ouvert et que tout va bien en essayant de lister le répertoire distant. Et à partir de maintenant, en appelant ftpRequest.GetResponse() (où ftpRequest.Method est WebRequestMethods.Ftp.ListDirectory), j'obtiens WebException avec le statut: Undefined, et description: la limite de temps pour cette opération a été atteinte. Lorsque je redémarre l'application, le problème disparaît.

Je ne trouve aucun autre endroit où les cours d'eau ne sont pas libérés correctement, et ne savent pas quoi faire ..

Répondre

1

Etes-vous sûr vous fermez le flux correctement et libérer ainsi toutes les ressources sous-jacentes correctement ? Si ce n'est pas le cas, cela peut être la cause de votre problème lorsque vous atteignez une limite (par exemple, sockets ouverts) après des échecs répétés.

+0

Eh bien, je n'ai pas appelé requestStream.Close() après la première erreur est survenue dans le bloc catch (WebException) .. Maintenant, je vois .. Serait-ce ce si simple? :) Merci beaucoup! – Agata

0

Une source d'erreur que j'ai rencontrée est la création d'un nouveau "NetworkCredential" encore et encore. Ensuite, vous aurez une exception après un certain temps.

+0

J'ai lu à propos de ce problème "Network Credential", mais je ne pense pas que ce soit un cas ici. J'ai des serveurs qui ont des fichiers téléchargés toutes les demi-heures, six jours par semaine et le problème ne s'est jamais produit. Cela se produit uniquement dans ce scénario particulier - lorsque les deux premières tentatives échouent lors du téléchargement du fichier. Je pense que David a bien compris. Nous verrons .. – Agata

+0

Eh bien ... J'ai dit "possible". :-) J'ai eu ce problème moi-même dans une application qui a fonctionné de la même manière que la vôtre, et ce qui est marrant, c'est qu'il a été utilisé pendant une longue période pour transférer des fichiers sur un serveur IIS sans problème. Mais quand nous avons commencé à transférer des fichiers sur un serveur Unix, cette erreur est apparue! –

1

Vous devez vous assurer que vous avez placé les éléments Stream.Close(), Request.Close() et Response.Close() dans un bloc finally, sinon ils seront ignorés en cas d'erreur. Gardez à l'esprit lorsque vous traitez avec des ressources externes telles que sur un réseau, vous devez programmer pour attendre des erreurs, car ils vont certainement surgir à un moment donné.

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