【问题标题】:c# ftpwebrequest performancec# ftpwebrequest 性能
【发布时间】:2013-07-17 20:12:52
【问题描述】:

我有一个从 Unix FTP 服务器下载文件的应用程序。它工作正常,只是有这个性能问题:大小为

也许这一次对于一些普通用户来说还可以,但对于我的应用程序来说是不可接受的,因为我需要下载数千个文件。

我尽可能地优化代码: - 用于读取内容的缓存和缓冲区在类的构造函数中创建了 1 次。 - 我创建了 1 次网络凭据,并在每次文件下载时重复使用。我知道这是可行的,因为第一个文件需要 7 秒才能下载,而所有后续下载都在 2 秒范围内。 - 我将缓冲区的大小从 2K 更改为 32K。我不知道这是否有帮助,因为我下载的文件小于1K,所以理论上缓冲区将被网络1轮内的所有信息填充。

也许与网络无关,但与我的写作方式和/或 windows 处理文件的写入方式有关??

有人可以给我一些关于如何减少时间到类似于 filezilla 的提示吗? 我需要减少时间,否则我的 ftp 将每天 24 小时运行 3 天以完成任务:( 提前谢谢了。 这里的代码:不完整,只是显示下载部分。

//Create this on the constructor of my class
downloadCache = new MemoryStream(2097152);
downloadBuffer = new byte[32768];

public bool downloadFile(string pRemote, string pLocal, out long donwloadTime)
{
FtpWebResponse response = null;
Stream responseStream = null;

try
{
    Stopwatch fileDownloadTime = new Stopwatch();
    donwloadTime = 0;
    fileDownloadTime.Start();

    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(pRemote);
    request.Method = WebRequestMethods.Ftp.DownloadFile;
    request.UseBinary = false;
    request.AuthenticationLevel = AuthenticationLevel.None;
    request.EnableSsl = false;
    request.Proxy = null;
    //I created the credentials 1 time and re-use for every file I need to download
    request.Credentials = this.manager.ftpCredentials; 

    response = (FtpWebResponse)request.GetResponse();
    responseStream = response.GetResponseStream();

    downloadCache.Seek(0, SeekOrigin.Begin);
    int bytesSize = 0;
    int cachedSize = 0;

    //create always empty file. Need this because WriteCacheToFile just append the file
    using (FileStream fileStream = new FileStream(pLocal, FileMode.Create)) { }; 

    // Download the file until the download is completed.
    while (true)
    {
        bytesSize = responseStream.Read(downloadBuffer, 0, downloadBuffer.Length);
        if (bytesSize == 0 || 2097152 < cachedSize + bytesSize)
        {
            WriteCacheToFile(pLocal, cachedSize);
            if (bytesSize == 0)
            {
                break;
            }
            downloadCache.Seek(0, SeekOrigin.Begin);
            cachedSize = 0;   
        }
        downloadCache.Write(downloadBuffer, 0, bytesSize);
        cachedSize += bytesSize;
    }

    fileDownloadTime.Stop();
    donwloadTime = fileDownloadTime.ElapsedMilliseconds;

    //file downloaded OK
    return true;
}
catch (Exception ex)
{
    return false;
}
finally
{
    if (response != null)
    {
        response.Close();
    }

    if (responseStream != null)
    {
        responseStream.Close();
    }
}
}

private void WriteCacheToFile(string downloadPath, int cachedSize)
{
using (FileStream fileStream = new FileStream(downloadPath, FileMode.Append))
{
    byte[] cacheContent = new byte[cachedSize];
    downloadCache.Seek(0, SeekOrigin.Begin);
    downloadCache.Read(cacheContent, 0, cachedSize);
    fileStream.Write(cacheContent, 0, cachedSize);
}
} 

【问题讨论】:

  • 我忘了说:我使用多个线程同时下载许多文件。

标签: c# performance download ftpwebrequest


【解决方案1】:

在我看来,您的问题与 TCP 客户端中使用的Nagels algorithm 有关。

您可以尝试关闭 Nagel 算法并将 SendChunked 设置为 false。

【讨论】:

  • 谢谢sean717。我阅读了有关 Nagels 算法的信息。我还阅读了有关如何关闭它的 msdn 文档,它说将 Socket.NoDelay 属性设置为 true 或 false。但是,这是在套接字级别,我的应用程序使用更高的类:FtpWebRequest。如何从我的代码中访问 NoDelay 属性??
  • 嘿,请看this question。基本上 FtpWebRequest 是从 System.Net.WebRequest 派生的,您可以从中关闭 Nagel。
  • 我添加了以下几行:ServicePoint spTemp = request.ServicePoint; spTemp.UseNagleAlgorithm = false;我需要测试这是否有效,因为link 表示“此属性的值不会影响现有的 ServicePoint 对象。只有更改后创建的新服务点会受到影响”
猜你喜欢
  • 2010-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多