Ich habe folgendes Problem: Ich verwende C#-ftp-Methoden, um das Senden von Dateien an FTP-Server zu automatisieren. Das Programm läuft ständig und überprüft vordefinierte Verzeichnisse. Wenn es Dateien in einem Verzeichnis findet, soll es diese auf einen definierten FTP-Server hochladen. Es gibt etwa 80 Verzeichnisse und die meiste Zeit hat das Programm etwas zu tun. Alles funktioniert gut, bis auf das folgende Szenario:
- Die Datei wird gerade hochgeladen.
- Beim Hochladen tritt ein Fehler auf: Der Remote-Host ist ausgefallen, die Quote ist überschritten oder ähnliches.
- Bei einem erneuten Versuch, die Datei hochzuladen, tritt der Fehler erneut auf.
-
Es wird versucht, die Datei zum dritten, vierten, ... Mal hochzuladen und dann diese Codezeile:
Stream requestStream = ftpRequest.GetRequestStream();
wirft WebException mit Status: Undefined, and description: the time limit for this operation has been reached (oder so ähnlich - ich musste das aus dem Polnischen übersetzen). Während diese WebException ausgelöst wird, sind FTP-Anfragen an andere Server (Dateien aus verschiedenen Verzeichnissen) erfolgreich, also sieht es so aus, als gäbe es nur ein Problem mit der Verbindung zu diesem einen FTP-Server.
Dies führt dazu, dass kein weiterer Versuch, die Datei hochzuladen, erfolgreich ist. Das Hochladen dieser Datei über einen anderen FTP-Client ist jedoch möglich. Wenn ich das Programm neu starte, läuft alles reibungslos. Sollte ich die ftp-Ressource irgendwie manuell freigeben? Ich verwende die KeepAlive-Eigenschaft von FtpWebRequest, die auf true. gesetzt ist.
Ich wäre sehr dankbar, wenn jemand etwas Licht in dieses Problem bringen könnte.
Bearbeitet:
Ich habe Davids Hinweis befolgt und die Stelle gefunden, an der ich die Close()-Methode für den requestStream nicht aufgerufen habe, ich habe es behoben, aber das Problem trat erneut auf.
Ich werde dann einen Code einfügen. Hier ist ein Teil der Methode, die die Datei auf den Server hochlädt. Wenn es fehlschlägt, wird ein weiterer Versuch unternommen, etwas wie:
while (retryCounter++ < retryNumber)
{
//upload file,
//if succeeded, break
}
innerhalb des while-Blocks gibt es:
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());
}
Das Szenario ist also wieder folgendes:
1. Die Datei wird hochgeladen und eine System.Net.Sockets.SocketException tritt auf.
2. Ein weiterer Versuch wird unternommen und System.Net.Sockets.SocketException tritt erneut auf.
3. Bevor ich die uploadfile-Methode aufrufe, prüfe ich immer, ob der entfernte Server läuft und alles in Ordnung ist, indem ich versuche, das entfernte Verzeichnis aufzulisten. Und von nun an, durch den Aufruf von ftpRequest.GetResponse() (wobei ftpRequest.Method gleich WebRequestMethods.Ftp.ListDirectory ist) erhalte ich eine WebException mit Status: Undefiniert und Beschreibung: Das Zeitlimit für diesen Vorgang wurde erreicht. Wenn ich die Anwendung neu starte, verschwindet das Problem.
Ich kann keine andere Stelle finden, an der die Streams nicht ordnungsgemäß freigegeben werden, und habe keine Ahnung, was ich als nächstes tun soll.