Как улучшить производительность FtpWebRequest? - PullRequest
34 голосов
/ 19 июня 2009

У меня есть приложение, написанное на .NET 3.5, которое использует FTP для загрузки / выгрузки файлов с сервера. Приложение работает нормально, но есть проблемы с производительностью:

  1. Требуется много времени для подключения к FTP-серверу. FTP-сервер находится в другой сети и имеет Windows 2003 Server (IIS FTP). Когда несколько файлов ставятся в очередь для загрузки, переход из одного файла в другой создает новое соединение с использованием FTPWebRequest, и это занимает много времени (около 8-10 секунд).

  2. Возможно ли повторно использовать соединение? Я не очень уверен насчет свойства KeepAlive. Какие соединения поддерживаются и используются повторно.

  3. IIS-FTP в Windows Server 2003 не поддерживает SSL, поэтому любой может легко увидеть имя пользователя / пароль через анализатор пакетов, например WireShark. Я обнаружил, что Windows Server 2008 поддерживает SSL через FTP в своей новой версии, если IIS 7.0.

Я хочу улучшить производительность загрузки / выгрузки моего приложения. Любые идеи будут оценены.

** Обратите внимание, что 3 не проблема, но я хотел бы, чтобы у людей были комментарии к ней

Ответы [ 18 ]

1 голос
/ 27 июня 2009

Я бы рекомендовал переключиться на rsync .
Плюсы:
Оптимизирован для сокращения времени передачи.
Поддерживает SSH для безопасной передачи
Использует TCP, что делает ваш ИТ-отдел / брандмауэр счастливее

Минусы:
Нет собственной поддержки .NET
Направлен на установку Linux-серверов - хотя есть приличные порты Windows, такие как DeltaCopy

В целом, хотя это гораздо лучший выбор, чем FTP

1 голос
/ 27 июня 2009

У меня были хорошие результаты с библиотекой ftp EDT:

http://www.enterprisedt.com/products/edtftpnet/overview.html

0 голосов
/ 08 мая 2018

Я сделал несколько тестов FtpWebRequest, аналогично ответу @Sid выше. Установка KeepAlive в true улучшает, но не асинхронные вызовы в моем тесте. Тест состоит из

1) FtpWebRequest для проверки существования файла 2) FtpWebRequest для загрузки 3) FtpWebRequest для переименования файла на сервере

Test FTP client 30 files of size 5 Kbytes took ... 14.897 seconds Test upload (alive true, connection name) 30 files of size 5 Kbytes took ... 34.229 seconds Test async(alive true, connection name) 30 files of size 5 Kbytes took ... 40.659 seconds Test send thread (alive true, connection name) 30 files of size 5 Kbytes took ... 38.926 seconds, 30 files

что улучшило, так это реализацию FTP-клиента, сделанную с использованием класса Socket

эталон здесь

https://github.com/pedro-vicente/ftp_t

0 голосов
/ 15 февраля 2016

Попробуйте этот код ниже, вы получите лучшую производительность:

private void Upload144_Click(object sender, EventArgs e)
{
    OpenFileDialog fileobj = new OpenFileDialog();
    fileobj.InitialDirectory = "C:\\";
    //fileobj.Filter = "Video files (*.mp4)";
    //fileobj.ShowDialog();

    if (fileobj.ShowDialog() == DialogResult.OK)
    {
        if (fileobj.CheckFileExists)
        {
            string test = Properties.Settings.Default.Connection;
            SqlConnection con = new SqlConnection(test);
            con.Open();
            string correctfilename = System.IO.Path.GetFileName(fileobj.FileName);
            SqlCommand cmd = new SqlCommand("Insert into Path(ID,Path5) VALUES   ((select isnull(MAX(id),0) + 1 from Path),'\\Videos\\" + correctfilename + "')", con);

            cmd.ExecuteNonQuery();

            string path = Application.StartupPath.Substring(0, Application.StartupPath.Length - 10);
            con.Close();

            //For Progressbar
            DataTable dt = new DataTable();
       //   SqlDataAdapter da = new SqlDataAdapter(cmd);
       //   da.Fill(dt);

            timer5.Enabled = true;

            // FOR FtpServer File Upload::
            string uploadfile = fileobj.FileName;
            string uploadFileName = new FileInfo(uploadfile).Name;

            string uploadUrl = "ftp://ftp.infotech.com/";
            FileStream fs = new FileStream(uploadfile, FileMode.Open, FileAccess.Read);
            try
            {
                long FileSize = new FileInfo(uploadfile).Length; // File size of file being uploaded.
                Byte[] buffer = new Byte[FileSize];

                fs.Read(buffer, 0, buffer.Length);

                fs.Close();
                fs = null;
                string ftpUrl = string.Format("{0}/{1}", uploadUrl, uploadFileName);
                FtpWebRequest requestObj = FtpWebRequest.Create(ftpUrl) as FtpWebRequest;
                requestObj.Method = WebRequestMethods.Ftp.UploadFile;
                requestObj.Credentials = new NetworkCredential("test@sample.com", "test@123");
                Stream requestStream = requestObj.GetRequestStream();
                requestStream.Write(buffer, 0, buffer.Length);

                requestStream.Flush();
                requestObj = null;
            }
            catch (Exception ex)
            {
                //MessageBox.Show("File upload/transfer Failed.\r\nError Message:\r\n" + ex.Message, "Succeeded", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
    }
}
0 голосов
/ 27 сентября 2015

Я работал несколько дней с этим ... и скорость была действительно низкой, ничего не сравнимо с FileZilla ... наконец я решил с многопоточностью. 10 потоков, создающих соединения для загрузки, дают мне хорошую скорость, может быть, даже могли бы быть улучшены еще ... со стандартной конфигурацией ftprequest

PeticionFTP.ConnectionGroupName = "MyGroupName"
PeticionFTP.ServicePoint.ConnectionLimit = 4
PeticionFTP.ServicePoint.CloseConnectionGroup("MyGroupName")

PeticionFTP.KeepAlive = False 
PeticionFTP.UsePassive = False

PeticionFTP.UseBinary = True

PeticionFTP.Credentials = New NetworkCredential(lHost.User, lHost.Password)
0 голосов
/ 21 февраля 2012

Один совет:

НИЖНИЕ БУФЕРНЫЕ / РАЗМЕРНЫЕ РАЗМЕРЫ ЗНАЧИТЕЛЬНО СНИЖАЮТ ЭФФЕКТИВНОСТЬ

Причина: еще много дискового ввода-вывода, памяти ввода-вывода, инициализация ftp-потока и многие другие факторы

0 голосов
/ 27 июня 2009

AFAIK, каждый запрос FtpWebRequest должен устанавливать новое соединение, включая вход на сервер. Если вы хотите ускорить FTP-передачу, я бы порекомендовал вам использовать альтернативный FTP-клиент. Некоторые из этих альтернативных клиентов могут войти в систему и затем выполнить несколько действий, используя одно и то же командное соединение.

Примеры таких клиентов включают: http://www.codeproject.com/KB/IP/FtpClient.aspx, который также содержит хорошее объяснение того, почему эти библиотеки могут работать быстрее, чем стандартный FtpWebRequest, и http://www.codeproject.com/KB/macros/ftp_class_library.aspx, который также выглядит как достаточно простая реализация.

Лично я откатил свою собственную реализацию FTP в .NET 1.1 за несколько дней до введения FtpWebRequest, и это все еще хорошо работает для .NET 2.0 и более поздних версий.

0 голосов
/ 23 июня 2009

KeepAlive работает. FtpWebRequest кэширует соединения внутри, так что они могут быть повторно использованы через некоторое время. Для получения подробной информации и объяснения этого механизма вы можете обратиться к ServicePoint .

Другим хорошим источником информации является поиск в источнике FtpWebRequest (вы можете сделать это на VS2008).

...