13.2. Класс QHttp.

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

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

Рассмотрим принцип действия QHttp на примере приложения, которое пытается получить HTML-файл с сайта Trolltech. Мы не будем здесь приводить содержимое заголовочного файла, т.к. он очень похож на тот, который использовался в предыдущем разделе. Различие состоит лишь в том, что теперь приватный слот объявлен под именем httpDone(bool) и изменено объявление одной приватной переменной (http типа QHttp).

MainWindow::MainWindow(QWidget *parent, const char *name) : QMainWindow(parent, name) { ... connect(&http, SIGNAL(done(bool)), this, SLOT(httpDone(bool))); } В конструкторе выполняется соединение сигнала done(bool), объекта QHttp, со слотом главного окна -- httpDone(bool). void MainWindow::getFile() { file.setName("aboutqt.html"); if (!file.open(IO_WriteOnly)) { QMessageBox::warning(this, tr("HTTP Get"), tr("Cannot write file %1\n%2.") .arg(file.name()) .arg(file.errorString())); return; } http.setHost("doc.trolltech.com"); http.get("/3.2/aboutqt.html", &file); http.closeConnection(); } Функция getFile() загружает файл http://doc.trolltech.com/3.2/aboutqt.html и сохраняет его в текущем каталоге, под именем aboutqt.html.

Объект QFile пытается открыть файл на запись, после этого в очередь помещается последовательность из трех HTTP-команд. Второй аргумент функции get() определяет устройство, куда будут записаны полученные данные.

HTTP-запросы исполняются в цикле обработки событий. По завершении заданной последовательности команд, объект Qhttp выдает сигнал done(bool), который поступает в слот httpDone(bool).

void MainWindow::httpDone(bool error) { if (error) QMessageBox::warning(this, tr("HTTP Get"), tr("Error while fetching file with " "HTTP: %1.") .arg(http.errorString())); file.close(); } После того, как запрос будет выполнен, файл закрывается. При возникновении ошибки перед пользователем выводится соответствующее сообщение.

Среди всего прочего, QHttp предоставляет в распоряжение программиста следующие функции: setHost(), get(), post() и head(). Ниже приводится пример передачи списка пар "имя = значение" в CGI-скрипт:

http.setHost("www.example.com"); http.post("/cgi/somescript.py", QCString("x=200&y=320"), &file); Для выполнения произвольных HTTP-запросов можно использовать более универсальную функцию request(), например: QHttpRequestHeader header("POST", "/search.html"); header.setValue("Host", "www.trolltech.com"); header.setContentType("application/x-www-form-urlencoded"); http.setHost("www.trolltech.com"); http.request(header, QCString("qt-interest=on&search=opengl")); Перед началом выполнения очередной операции, QHttp выдает сигнал requestStarted(int), а после окончания -- requestFinished(int, bool). Аргумент int определяет идентификационный номер запроса. Если вас интересует ход выполнения отдельных команд, то вам придется сохранять их идентификационные номера, при вызове соответствующей функции. Благодаря этому появится возможность предоставить пользователю более детальную информацию о ходе процесса.

Однако, в большинстве приложений нас интересует только результат выполнения всей последовательности команд. В этом случае мы просто соединяемся с сигналом done(bool), который выдается после выполнения последней команды в последовательности.

При возникновении ошибки, очередь команд автоматически очищается. Это означает, что все последующие команды никогда не будут выполнены. Но если в очередь будут поставлены другие команды уже после возникновения ошибки, то они будут исполнены как ни в чем не бывало.

Подобно QFtp, объекты класса QHttp имеют в своем распоряжении сигнал readyRead(), и функции readBlock() и readAll(), которые могут использоваться в том случае, когда функции get() не передается устройство для записи. Кроме того, этот класс так же имет сигнал dataTransferProgress(int, int), который может быть напрвлен в слот setProgress(int, int) класса QProgressBar или QProgressDialog.