底层连接已关闭:接收时发生意外错误
我来这里是因为我在通过 ftp 协议下载一些文件时遇到问题。这很奇怪,因为它偶尔会发生,甚至对于同一个文件也是如此。
只是一个精度:我正在下载非常大的文件(从 500 Mo 到 30Go)
以下是我的函数返回的异常类型:(对不起,它是法语)
System.Net.WebException:La connexion sous-jacente a重要信息: 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, Int32creationTimeout, Boolean canReuse) à System.Net.FtpWebRequest.FinishRequestStage(RequestStage 阶段) à System.Net.FtpWebRequest.SyncRequestCallback(Object obj) à System.Net.CommandStream.Abort(异常 e) à System.Net.CommandStream.CheckContinuePipeline() à System.Net.FtpDataStream.System.Net.ICloseEx.CloseEx(CloseExState closeState) à System.Net.FtpDataStream.Dispose(布尔处置) à 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”假设是最一致的。今晚我将尝试使用较大的超时值。
I'm here because I have a problem while downloading some files through ftp protocol. It's weird because it occurs occasionally and even for the same single file.
Just a precision: I'm downloading very large files (from 500 Mo to 30Go)
Here are the kind of Exceptions returned by my function : (sorry it's in french)
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)
Here is the code used to download :
the download methods :
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;
}
the Exists method :
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;
}
Maybe it's a timeout problem, but i don't really know. I searched for a long time for an answer but without success. Maybe some of you will have a solution.
///
EDIT : Some progress :
I have tested my code in debug mode with VS and in fact the Exception above is the consequence of a previous one. (I Couldn't know that because I only wrote the last Exception returned in a log file)
Here is the original exception :
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.
The second exception is caused by this part of the Download method code :
catch (Exception e)
{
fileStream.Close();
responseStream.Close(); // <<<<<<<<<<<<<<
response.Close();
throw e;
}
I keep on my investigations but it seems that the "timeout pb" hypothesis is the most consistent. I will try with a large timeout value tonight.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
只是想加强ScottE的诊断,并且更加具体。超时很可能是问题所在。
FtpWebRequest 的 .Net 实现错误或MSDN 文档< /a> 有一个拼写错误,FtpWebRequest.Timeout 的默认值不是 -1(无限)。为 100000(100 秒)。
此外还有另一个超时问题。一些测试表明,responseStream 的超时值始终为 300000(300 秒)。我不知道这个值是如何分配的。无论如何,需要修改该值以适应大文件。
综上所述,解决方案是将FtpWebRequest.Timeout和Stream.Timeout设置为足够大的值。
Just want to strengthen ScottE's diagnosis, and be more specific. Timeout is most likely the issue.
Either .Net implementation of FtpWebRequest is erroneous or the MSDN document has a typo, the default value of FtpWebRequest.Timeout is not -1 (Infinite). It is 100000 (100 seconds).
In addition there is another timeout issue. A few tests have shown that responseStream always has a timeout value of 300000 (300 seconds). I do not know how this value is assigned. Anyways, this value needs to be modified to accommodate large files.
In summary, the solution is to set FtpWebRequest.Timeout and Stream.Timeout to a sufficiently large value.
这里有一个很好的尝试线索:
http://social.msdn.microsoft.com/Forums/en/ncl/thread/47634ec2-4d40-4d3f-b075-8cc92bfa2b24
增加超时至少是一个好主意。
Here's a good thread of things to try:
http://social.msdn.microsoft.com/Forums/en/ncl/thread/47634ec2-4d40-4d3f-b075-8cc92bfa2b24
Increasing the timeout is probably a good idea in the least.
这可能是 Windows 防火墙设置存在问题的症状。禁用“服务”界面中的“应用程序层网关服务”为我解决了这个问题。
该线程有很多信息:
http://forum.parallels.com /pda/index.php/t-57966.html
This could be a symptom of an issue with the settings of your Windows Firewall. Disabling the "Application Layer Gateway Service" in the "services" interface fixed it for me.
This thread has a lot of information:
http://forum.parallels.com/pda/index.php/t-57966.html
尝试设置:
Try setting: