- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания QT 4 программирование GUI на С++ Жасмин Бланшет
Шрифт:
Интервал:
Закладка:
header.setValue("Host", "www.trolltech.com");
header.setContentType("application/x-www-form-urlencoded");
http.setHost(www.trolltech.com);
http.request(header, "qt-interest=on&search=opengl");
QHttp генерирует сигнал requestStarted(int) в начале выполнения команды и сигнал requestFinished(int, bool) после завершения выполнения команды. Параметр типа int является числом, которое идентифицирует запрос. Если мы собираемся отслеживать результаты выполнения отдельных запросов, мы можем сохранять эти идентификаторы при постановке запросов в очередь. Отслеживание идентификаторов обеспечивает более оперативную обратную связь с пользователем.
В большинстве приложений нас интересует результат исполнения всей последовательности команд. Это легко достигается путем подсоединения сигнала done(bool), который генерируется всякий раз, когда очередь запросов становится пустой.
При возникновении ошибки очередь запросов автоматически очищается. Но если мы после возникновения ошибки зададим новые запросы с использованием того же объекта QHttp, они будут поставлены в очередь и затем выполнены в обычном порядке.
Как и QFtp, класс QHttp содержит сигнал readyRead(), а также функции read() и readAll(), которые мы можем использовать вместо указания устройства ввода—вывода.
Написание клиент—серверных приложений на базе TCP
Классы QTcpSocket и QTcpServer могут использоваться для реализации клиентов и серверов TCP. TCP — это транспортный протокол, который составляет основу большинства прикладных протоколов сети Интернет, включая FTP и HTTP, и который может также использоваться для создания пользовательских протоколов.
TCP является потокоориентированным протоколом. Для приложений данные представляются в виде большого потока данных, очень напоминающего большой однородный файл. Протоколы высокого уровня, построенные на основе TCP, являются либо строкоориентированными, либо блокоориентированными:
• строкоориентированные протоколы передают текстовые данные построчно, завершая каждую строку символом перехода на новую строку;
• блокоориентированные протоколы передают данные в виде двоичных блоков. Каждый блок имеет в начале поле, где указан его размер, и затем идут байты данных.
Класс QTcpSocket наследует QIODevice через класс QAbstractSocket, и поэтому чтение с него или запись на него могут производиться с применением средств класса QDataStream или QTextStream. Одно существенное отличие чтения данных из сети по сравнению с чтением обычного файла заключается в том, что мы должны быть уверены в получении достаточного количества данных от партнерского узла (peer) перед использованием оператора >>. В противном случае результат может быть непредсказуемым.
В данном разделе мы рассмотрим программный код клиента и сервера, которые используют пользовательский протокол блочной передачи. Клиент называется Trip Planner (планировщик путешествий) и позволяет пользователям составлять план путешествия на поезде. Сервер называется Trip Server (сервер путешествий) и обеспечивает клиента информацией о путешествии. Мы начнем с написания клиентского приложения Trip Planner.
Приложение Trip Planner содержит поле From (из пункта), поле To (до пункта), поле Date (дата), поле Approximate Time (приблизительное время) и два переключателя, определяющие приблизительное время отправления или прибытия. Когда пользователь нажимает клавишу Search, приложение посылает запрос на сервер, который возвращает список железнодорожных рейсов, которые удовлетворяют критериям пользователя. Этот список отображается в виджете QTableWidget в окне Trip Planner. В нижней части окна расположены текстовая метка QLabel, показывающая состояние последней операции, и индикатор состояния процесса QProgressBar.
Рис. 14.1. ПриложениеТпр Planner.
Пользовательский интерфейс приложения Trip Planner был создан при помощи QtDesigner в файле tripplanner.ui. Ниже мы основное внимание уделим исходному коду подкласса QDialog, который реализует функциональность приложения:
#include "ui_tripplanner.h"
01 class TripPlanner : public QDialog, public Ui::TripPlanner
02 {
03 Q_OBJECT
04 public:
05 TripPlanner(QWidget *parent = 0);
06 private slots:
07 void connectToServer();
08 void sendRequest();
09 void updateTableWidget();
10 void stopSearch();
11 void connectionClosedByServer();
12 void error();
13 private:
14 void closeConnection();
15 QTcpSocket tcpSocket;
16 quint16 nextBlockSize;
17 };
Класс TripPlanner наследует не только QDialog, но и Ui::TripPlanner (который генерируется компилятором uic, используя файл tripplanner.ui). Переменная—член tcpSocket инкапсулирует соединение TCP. Переменная nextBlockSize используется при синтаксическом анализе блоков, поступивших с сервера.
01 TripPlanner::TripPlanner(QWidget *parent)
02 : QDialog(parent)
03 {
04 setupUi(this);
05 QDateTime dateTime = QDateTime::currentDateTime();
06 dateEdit->setDate(dateTime.date());
07 timeEdit->setTime(QTime(dateTime.time().hour(), 0));
08 progressBar->hide();
09 progressBar->setSizePolicy(QSizePolicy::Preferred,
10 QSizePolicy::Ignored);
11 tableWidget->verticalHeader()->hide();
12 tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
13 connect(searchButton, SIGNAL(clicked()),
14 this, SLOT(connectToServer()));
15 connect(stopButton, SIGNAL(clicked()), this, SLOT(stopSearch()));
16 connect(&tcpSocket, SIGNAL(connected()),
17 this, SLOT(sendRequest()));
18 connect(&tcpSocket, SIGNAL(disconnected()),
19 this, SLOT(connectionClosedByServer()));
20 connect(&tcpSocket, SIGNAL(readyRead()),
21 this, SLOT(updateTableWidget()));
22 connect(&tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
23 this, SLOT(error()));
24 }
В конструкторе мы инициализируем поля редактирования даты и времени текущей датой и временем. Мы также не показываем индикатор состояния программы, потому что он необходим только при активном соединении. В Qt Designer свойства minimum и maximum индикатора состояния устанавливались в 0. Это определяет поведение QProgressBar как индикатора занятости вместо стандартного индикатора, показывающего процент выполнения работы.
В конструкторе мы также связываем сигналы connected(), disconnected(), readyRead() и error(QAbstractSocket::SocketError) класса QTcpSocket с закрытыми слотами.
01 void TripPlanner::connectToServer()
02 {
03 tcpSocket.connectToHost("tripserver.zugbahn.de", 6178);
04 tableWidget->setRowCount(0);
05 searchButton->setEnabled(false);
06 stopButton->setEnabled(true);
07 statusLabel->setText(tr("Connecting to server..."));
08 progressBar->show();
09 nextBlockSize = 0;
10 }
Слот connectToServer() выполняется, когда пользователь нажимает клавишу Search для запуска процедуры поиска. Мы вызываем функцию connectToHost() объекта типа QTcpSocket для подсоединения к серверу, который, как мы предполагаем, доступен через порт 6178 по вымышленному адресу хоста tripserver.zugbahn.de. (Если вы собираетесь проверить работу этого примера на вашей машине, замените имя хоста на QHostAddress::LocalHost.) Вызов connectToHost() выполняется асинхронно; эта функция всегда немедленно возвращает управление. Соединение обычно устанавливается позже. Объект QTcpSocket генерирует сигнал connected(), если соединение успешно осуществлено и действует, или error(QAbstractSocket::SocketError), если соединение завершилось неудачей.
Затем мы обновляем интерфейс пользователя, в частности делаем видимым индикатор состояния приложения.
Наконец, мы устанавливаем переменную nextBlockSize на 0. Эта переменная содержит длину следующего блока, полученного от сервера. Мы задали значение 0, поскольку еще не знаем размер следующего блока.
01 void TripPlanner::sendRequest()
02 {
03 QByteArray block;
04 QDataStream out(&block, QIODevice::WriteOnly);
05 out.setVersion(QDataStream::Qt_4_1);
06 out << quint16(0) << quint8('S') << fromComboBox->currentText()
07 << toComboBox->currentText() << dateEdit->date()
08 << timeEdit->time();
09 if (departureRadioButton->isChecked()) {
10 out << quint8('D');
11 } else {
12 out << quint8('A');
13 }
14 out.device()->seek(0);
15 out << quint16(block.size() - sizeof(quint16));
16 tcpSocket.write(block);
17 statusLabel->setText(tr("Sending request..."));
18 }
Слот sendRequest() выполняется, когда объект QTcpSocket генерирует сигнал connected(), уведомляя об установке соединения. Задача этого слота — сгенерировать запрос к серверу с передачей всей введенной пользователем информации.