list()

emit listInfo(file_N_1)

get(file_N_1)

emit listInfo(file_N_2)

get(file_N_2)

emit done()

Если файл фактически оказывается каталогом, он добавляется в список pendingDirs и, когда завершается скачивание последнего файла, полученного текущей командой list(), выдается новая команда cd(), за которой следует новая команда list() для следующего каталога, ожидающего обработки, и весь процесс повторяется для нового каталога. Скачиваются новые файлы, и в список pendingDirs добавляются новые каталоги до тех пор, пока не будут скачаны все файлы из всех каталогов и список pendingDirs в результате не станет пустым.

Если возникнет сетевая ошибка при загрузке пятого файла, скажем, из двадцати файлов в каталоге, остальные файлы не будут скачаны. Если бы мы захотели скачать как можно больше файлов, то один из способов заключается в выполнении по одной операции GET и ожидании сигнала done(bool) перед выполнением новой операции GET. В функции listInfo() мы бы просто добавили имя файла в конец списка QStringList вместо немедленного вызова get(), а в слоте done(bool) мы бы вызывали функцию get() для следующего загружаемого файла из списка QStringList. Последовательность команд выглядела бы так:

connectToHost(host, port)

login()

cd(directory_1)

list()

cd(directory_N)

list()

emit listInfo(file_1_1)

emit listInfo(file_1_2)

emit listInfo(file_N_1)

emit listInfo(file_N_2)

emit done()

get(file_1_1)

emit done()

get(file_1_2)

emit done()

get(file_N_1)

emit done()

get(file_N_2)

emit done()

Еще одно решение могло бы заключаться в применении одного объекта QFtp для каждого файла. Это позволило бы нам скачивать файлы из сети параллельно, используя отдельные FTP—соединения.

01 int main(int argc, char *argv[])

02 {

03 QCoreApplication app(argc, argv);

04 QStringList args = app.arguments();

05 if (args.count() != 2) {

06 cerr << "Usage: spider url" << endl << "Example:" << endl

07 << " spider ftp://ftp.trolltech.com/freebies/leafnode" << endl;

08 return 1;

09 }

10 Spider spider;

11 if (!spider.getDirectory(QUrl(args[1])))

12 return 1;

13 QObject::connect(&spider, SIGNAL(done()), &app, SLOT(quit()));

14 return app.exec();

15 }

Функция main() завершает программу. Если пользователь не задает адрес URL в командной строке, мы выдаем сообщение об ошибке и завершаем программу.

В обоих примерах применения протокола FTP данные, полученные функцией get(), записывались в объект QFile. Это не обязательно должно быть так. Если бы мы захотели хранить данные в памяти, мы могли бы использовать QBuffer — подкласс QIODevice, являющийся оболочкой массива QByteArray. Например:

QBuffer *buffer= new QBuffer;

buffer->open(QIODevice::WriteOnly);

ftp.get(urlInfo.name(), buffer);

Мы могли бы также не задавать в функции get() аргумент с устройством ввода—вывода или передать нулевой указатель. Класс QFtp тогда генерирует сигнал readyRead() при поступлении каждой новой порции данных и данные могут считываться при помощи функции read() или readAll().

<p>Написание НТТР—клиента</p>

Класс QHttp реализует клиентскую часть протокола HTTP в Qt. Он содержит различные функции для выполнения самых распространенных операций протокола HTTP, включая get() и post(), и обеспечивает средство выполнения произвольных запросов HTTP. Если вы прочитали предыдущий раздел о классе QFtp, вы обнаружите, что существует много общего у классов QFtp и QHttp.

Класс QHttp работает асинхронно. Когда мы вызываем такие функции, как get() или post(), управление сразу же возвращается к нам, а пересылка данных осуществляется после передачи управления обратно в цикл обработки событий Qt. Это обеспечивает работоспособность интерфейса пользователя во время обработки запросов HTTP.

Перейти на страницу:

Похожие книги