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(█, 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(), уведомляя об установке соединения. Задача этого слота — сгенерировать запрос к серверу с передачей всей введенной пользователем информации.
Запрос является двоичным блоком следующего формата:
• quint16 — размер блока в байтах (не учитывая данное поле),
• quint8 — тип запроса (всегда «S»),
• QString — пункт отправления,
• QString — пункт прибытия,
• QDate — дата поездки,
• QTime — примерное время отправления или прибытия,
• quint8 — признак времени отправления («D») или прибытия («А»).
Сначала мы записываем данные в массив типа QByteArray с именем block. Мы не можем писать данные непосредственно в QTcpSocket, поскольку мы не знаем размер блока, который будет отсылаться первым, пока не разместим все данные в блоке.
Сначала мы записываем 0 в поле размера блока и затем размещаем остальные данные. Затем мы делаем вызов seek(0) для устройства ввода—вывода (для установки на начало буфера QBuffer, создаваемого автоматически классом QDataStream), чтобы встать на начало массива байтов и переписать первоначальный 0 фактическим размером блока данных. Эта величина рассчитывается как размер блока за вычетом sizeof(quint16) (то есть 2), чтобы исключить поле с размером блока из общей суммы байтов. После этого мы вызываем функцию write() для объекта QTcpSocket, чтобы отослать этот блок на сервер.
01 void TripPlanner::updateTableWidget()
02 {
03 QDataStream in(&tcpSocket);
04 in.setVersion(QDataStream::Qt_4_1);
05 forever {
06 int row = tableWidget->rowCount();