底层连接已关闭:接收时出现意外错误

底层连接已关闭:接收时出现意外错误

问题描述:

我在这里是因为在通过ftp协议下载某些文件时遇到问题。这很奇怪,因为它偶尔会出现,甚至是同一个文件。底层连接已关闭:接收时出现意外错误

只是精度:我下载非常大的文件(500莫30Go)

这里是那种通过我的函数返回的异常:(抱歉,这是法语)

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)

这里是用来下载代码:

的下载方法:

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; 
    } 

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; 
    } 

也许这是一个超时问题,但我真的不知道。我花了很长时间寻找答案,但没有成功。也许你们中的一些人会有解决方案。

///

编辑:一些进展:

我过我在调试模式下的代码与VS而事实上以上的例外是前一个的结果。 (我并不知道,因为我只写了最后一个异常的日志文件中返回)

原来这里是例外:

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. 

第二异常是由下载方法这部分代码引起的:

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

我一直在我的调查,但似乎“超时PB”假说是最稳定的。今晚我会尝试一个很大的超时值。

+1

不要道歉。我记得的唯一一部法语是“Je ne parle Francais”和“Je voudrais une kilo du pomme du terre,s'il vous plais”,这两个都不是很有用,可能是可怕的拼写:-)你做得更好工作比我在类似的情况下能够。 – paxdiablo 2011-06-10 09:51:04

+13

你的英语其实很不错。你已经设法问了一个问题,这个问题比许多访问这个网站并以英语作为第一语言的人更好的措辞和更好的结构。 – mdm 2011-06-10 09:52:48

+0

另外,如果您使用常规FTP客户端连接到网站会发生什么情况?你可以下载文件吗?听起来好像你和服务器之间存在连接错误 - 你的代码看起来不错。如果你把你的代码指向另一个FTP站点(也许是你的机器上的本地FTP服务器),那么怎么办?它会失败吗? – mdm 2011-06-10 09:55:20

这里的东西一个很好的线程尝试:

http://social.msdn.microsoft.com/Forums/en/ncl/thread/47634ec2-4d40-4d3f-b075-8cc92bfa2b24

增加超时可能是最少的一个好主意。

+0

我将尝试此解决方案。 – Hariboox 2011-06-10 10:17:45

+0

我不知道什么解决了这个问题,但它看起来与你正在经历的相似。大文件可能会变得复杂。 – ScottE 2011-06-10 10:22:51

+0

我想我现在已经接近解决方案。让我看看我的新编辑 – Hariboox 2011-06-10 16:38:06

只是想加强ScottE的诊断,并且更加具体。超时很可能是问题。

FtpWebRequest的.Net执行错误或the MSDN document有错字,FtpWebRequest.Timeout的默认值不是-1(无限)。它是100000(100秒)。

另外还有另一个超时问题。一些测试显示responseStream的超时值始终为300000(300秒)。我不知道这个值是如何分配的。无论如何,这个值需要修改,以适应大型文件。

总之,解决方案是将FtpWebRequest.Timeout和Stream.Timeout设置为足够大的值。

+0

我可以确认FtpWebRequest.Timeout文档是错误的。 @洪是正确的...它是100秒。 – 2013-02-12 05:30:22

这可能是Windows防火墙设置问题的症状。在“服务”界面中禁用“应用层网关服务”为我解决了这个问题。

这个讨论有很多信息:

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

+1

链接已死亡。 – 2015-05-29 21:19:10