底层连接已关闭:接收时发生意外错误

The underlying connection was closed: An unexpected error occurred on a receive(底层连接已关闭:接收时发生意外错误)
本文介绍了底层连接已关闭:接收时发生意外错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里是因为我在通过 ftp 协议下载一些文件时遇到问题.这很奇怪,因为它偶尔会发生,甚至对于同一个文件也是如此.

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.

只是一个精度:我正在下载非常大的文件(从 500 Mo 到 30Go)

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 阶段)à 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)

这里是用来下载的代码:

Here is the code used to download :

下载方式:

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

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

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.

///

一些进展:

我已经用 VS 在调试模式下测试了我的代码,实际上上面的异常是前一个异常的结果.(我不知道,因为我只写了日志文件中返回的最后一个异常)

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)

这是原来的例外:

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.

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

The second exception is caused by this part of the Download method code :

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

我继续调查,但似乎超时 pb"假设是最一致的.今晚我将尝试使用较大的超时值.

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.

推荐答案

只是想加强ScottE的诊断,更具体一些.超时很可能是问题所在.

Just want to strengthen ScottE's diagnosis, and be more specific. Timeout is most likely the issue.

FtpWebRequest 的 .Net 实现是错误的,或者 MSDN文档有错别字,FtpWebRequest.Timeout的默认值不是-1(Infinite).它是 100000(100 秒).

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).

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

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.

综上,解决方法是把 FtpWebRequest.Timeout 和 Stream.Timeout 设置为足够大的值.

In summary, the solution is to set FtpWebRequest.Timeout and Stream.Timeout to a sufficiently large value.

这篇关于底层连接已关闭:接收时发生意外错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)