c# .net connection webexception

c# - La conexión subyacente se cerró: se produjo un error inesperado en una recepción



.net connection (4)

Estoy aquí porque tengo un problema al descargar algunos archivos a través del protocolo ftp. Es raro porque ocurre ocasionalmente e incluso para el mismo archivo.

Solo una precisión: estoy descargando archivos muy grandes (de 500 Mo a 30Go)

Aquí está el tipo de excepciones devueltas por mi función: (lo siento, está en francés)

System.Net.WebException: La connexion sous-jacente a été fermée : Une erreur inattendue s''est produite lors de la réception. à System.Net.FtpWebRequest.CheckError() à System.Net.FtpWebRequest.SyncRequestCallback(Object obj) à System.IO.Stream.Close() à System.Net.ConnectionPool.Destroy(PooledStream pooledStream) à System.Net.ConnectionPool.PutConnection(PooledStream pooledStream, Object owningObject, Int32 creationTimeout, Boolean canReuse) à System.Net.FtpWebRequest.FinishRequestStage(RequestStage stage) à System.Net.FtpWebRequest.SyncRequestCallback(Object obj) à System.Net.CommandStream.Abort(Exception e) à System.Net.CommandStream.CheckContinuePipeline() à System.Net.FtpDataStream.System.Net.ICloseEx.CloseEx(CloseExState closeState) à System.Net.FtpDataStream.Dispose(Boolean disposing) à System.IO.Stream.Close() à UtilityClasses.FTP.Download(String srcDirectoryPath, String file, String destDirectoryPath)

Aquí está el código utilizado para descargar:

Los métodos de descarga:

public Dictionary<string, object> Download(string srcDirectoryPath, string file, string destDirectoryPath, int attemptLimitNb, int delay) { int attemptNb = 0; bool downloadFailed; Dictionary<string, object> result = new Dictionary<string,object>(); do { attemptNb++; result = Download(srcDirectoryPath, file, destDirectoryPath); downloadFailed = result["downloadfailed"] != null; if (downloadFailed) Thread.Sleep((int)(1000 * delay)); } while (downloadFailed && attemptNb < attemptLimitNb); return result; } public Dictionary<string, object> Download(string srcDirectoryPath, string file, string destDirectoryPath) { Exception downloadFailed = null; Dictionary<string, object> result = new Dictionary<string, object>(); bool fileFound = false; try { if (destDirectoryPath == null || !Directory.Exists(destDirectoryPath)) throw new Exception("Download destination path does not exist"); if (file != null && file != "") { if (file.Contains("/")) { throw new Exception("Invalid file name. Impossible to download"); } Uri serverUri; if (srcDirectoryPath == null || srcDirectoryPath == "") { serverUri = new Uri("ftp://" + this.Server + "/" + file); } else if (Regex.IsMatch(srcDirectoryPath, "^/.*$") || Regex.IsMatch(srcDirectoryPath, "^.*/$")) { throw new Exception("Path must not start and end with ''/''"); } else { serverUri = new Uri("ftp://" + this.Server + "/" + srcDirectoryPath + "/" + file); } if (serverUri.Scheme != Uri.UriSchemeFtp) throw new Exception("server URI Scheme does not match FTP URI Scheme"); if (Exists(srcDirectoryPath, file)) { fileFound = true; FtpWebRequest downloadRequest = (FtpWebRequest)FtpWebRequest.Create(serverUri); downloadRequest.Credentials = new NetworkCredential(UserName, Password); downloadRequest.KeepAlive = false; downloadRequest.Method = WebRequestMethods.Ftp.DownloadFile; FtpWebResponse response = (FtpWebResponse)downloadRequest.GetResponse(); Stream responseStream = response.GetResponseStream(); FileStream fileStream = new FileStream(Path.Combine(destDirectoryPath, file), FileMode.Create); byte[] buffer = new byte[2000]; int read = 0; try { do { read = responseStream.Read(buffer, 0, buffer.Length); fileStream.Write(buffer, 0, read); fileStream.Flush(); } while (read != 0); } catch (Exception e) { fileStream.Close(); responseStream.Close(); response.Close(); throw e; } fileStream.Close(); responseStream.Close(); response.Close(); } } } catch (WebException webExcptn) { downloadFailed = webExcptn; } finally { result.Add("filefound", fileFound); result.Add("downloadfailed", downloadFailed); } return result; }

el método Exists:

public bool Exists(string srcPath, string elementName) { if (elementName == null || elementName == "") { return false; } Uri serverUri; bool res = false; if (srcPath == null || srcPath == "") { serverUri = new Uri("ftp://" + this.Server); } else if (Regex.IsMatch(srcPath, "^/.*$") || Regex.IsMatch(srcPath, "^.*/$")) { throw new Exception("Path must not start and end with ''/''"); } else { serverUri = new Uri("ftp://" + this.Server + "/" + srcPath); } if (serverUri.Scheme != Uri.UriSchemeFtp) throw new Exception("server URI Scheme does not match FTP URI Scheme"); FtpWebRequest listingRequest = (FtpWebRequest)FtpWebRequest.Create(serverUri); listingRequest.Credentials = new NetworkCredential(UserName, Password); listingRequest.KeepAlive = false; listingRequest.Method = WebRequestMethods.Ftp.ListDirectory; FtpWebResponse response = (FtpWebResponse)listingRequest.GetResponse(); Stream responseStream = response.GetResponseStream(); StreamReader streamReader = new StreamReader(responseStream); string ftpElementName; do { ftpElementName = Path.GetFileName(streamReader.ReadLine()); if (ftpElementName == null) break; else { string pattern = "^" + elementName.Replace("[", "//[").Replace("]", "//]").Replace("+", "[+]").Replace(".", "[.]") + "$"; if (Regex.IsMatch(ftpElementName, pattern, RegexOptions.IgnoreCase)) { res = true; } } } while (ftpElementName != null && !res); streamReader.Close(); responseStream.Close(); response.Close(); return res; }

Tal vez sea un problema de tiempo fuera, pero realmente no lo sé. Busqué durante mucho tiempo una respuesta pero sin éxito. Tal vez algunos de ustedes tengan una solución.

///

EDITAR: Algunos avances:

He probado mi código en modo de depuración con VS y, de hecho, la excepción anterior es la consecuencia de una anterior. (No podría saberlo porque solo escribí la última excepción devuelta en un archivo de registro)

Aquí está la excepción original:

Unable to read data from the transport connection: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.

La segunda excepción se debe a esta parte del código del método de descarga:

catch (Exception e) { fileStream.Close(); responseStream.Close(); // <<<<<<<<<<<<<< response.Close(); throw e; }

Sigo con mis investigaciones pero parece que la hipótesis de "timeout pb" es la más consistente. Intentaré con un valor de tiempo de espera grande esta noche.



Esto podría ser un síntoma de un problema con la configuración de su Firewall de Windows. Deshabilitar el "Servicio de puerta de enlace de capa de aplicación" en la interfaz de "servicios" lo solucioné.

Este hilo tiene mucha información:

http://forum.parallels.com/pda/index.php/t-57966.html


Intenta configurar:

request.EnableSsl = true


Solo quiero fortalecer el diagnóstico de Scott, y ser más específico. El tiempo de espera es más probable que el problema.

Cualquiera de las implementaciones .Net de FtpWebRequest es errónea o el documento MSDN tiene un error tipográfico, el valor predeterminado de FtpWebRequest.Timeout no es -1 (Infinito). Es 100000 (100 segundos).

Además hay otro problema de tiempo de espera. Algunas pruebas han demostrado que responseStream siempre tiene un valor de tiempo de espera de 300000 (300 segundos). No sé cómo se asigna este valor. De todos modos, este valor necesita ser modificado para acomodar archivos grandes.

En resumen, la solución es establecer FtpWebRequest.Timeout y Stream.Timeout en un valor suficientemente grande.