Читаем QT 4: программирование GUI на С++ полностью

20 in >> from >> to >> date >> time >> flag;

21 srand(from.length * 3600 + to.length * 60 + time.hour);

22 int numTrips = rand % 8;

23 for (int i = 0; i < numTrips; ++i)

24 generateRandomTrip(from, to, date, time);

25 QDataStream out(this);

26 out << quint16(0xFFFF);

27 }

28 close;

29 }

Слот readClient подсоединяется к сигналу readyRead класса QTcpSocket. Если nextBlockSize равен 0, мы начинаем считывать размер блока; в противном случае он уже считан нами, и тогда мы проверяем поступление целого блока. Если это целый блок, мы считываем его за один шаг. Мы используем QDataStream непосредственно для QTcpSocket (объект this) и считываем поля, используя оператор >>.

После чтения запроса клиента мы готовы сформировать ответ. В реальном приложении мы осуществляли бы поиск информации в базе данных расписания железнодорожных рейсов и попытались бы найти подходящие рейсы. Но здесь мы воспользуемся функцией generateRandomTrip, которая случайным образом генерирует произвольный рейс. Мы вызываем эту функцию произвольное число раз и затем посылаем 0xFFFF для обозначения конца данных. В конце мы закрываем соединение.

01 void ClientSocket::generateRandomTrip(const QString & /* откуда */,

02 const QString & /* куда */, const QDate &date, const QTime &time)

03 {

04 QByteArray block;

05 QDataStream out(█, QIODevice::WriteOnly);

06 out.setVersion(QDataStream::Qt_4_1);

07 quint16 duration = rand % 200;

08 out << quint16(0) << date << time << duration << quint8(1)

09 << QString("InterCity");

10 out.device->seek(0);

11 out << quint16(block.size - sizeof(quint16));

12 write(block);

13 }

Функция generateRandomTrip демонстрирует способ пересылки блока данных через соединение TCP. Это очень напоминает то, что мы делали в клиенте в функции sendRequest. И вновь мы записываем блок в массив QByteArray таким образом, что мы можем определять его размер до того, как мы его отошлем с помощью функции write.

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

02 {

03 QApplication app(argc, argv);

04 TripServer server;

05 if (!server.listen(QHostAddress::Any, 6178)) {

06 cerr << "Failed to bind to port" << endl;

07 return 1;

08 }

09 QPushButton quitButton(QObject::tr("&Quit"));

10 quitButton.setWindowTitle(QObject::tr("Trip Server"));

11 QObject::connect(&quitButton, SIGNAL(clicked),

12 &app, SLOT(quit));

13 quitButton.show;

14 return app.exec;

15 }

В функции main мы создаем объект TripServer и кнопку QPushButton, которая позволяет пользователю остановить сервер. Работа сервера начинается с вызова функции QTcpSocket::listen, принимающей адрес IP и номер порта, по которому мы хотим принимать соединения. Специальный адрес 0.0.0.0 (QHostAddress::Any) соответствует наличию любого интерфейса IP на локальном хосте.

Этим завершается наш пример системы клиент—сервер. В данном случае нами использовался блокоориентированный протокол, позволяющий применять объект типа QDataStream для чтения и записи данных. Если бы мы захотели использовать строкоориентированный протокол, наиболее простым было бы применение функций canReadLine и readLine класса QTcpSocket в слоте, подсоединенном к сигналу readyRead:

QStringList lines;

while (tcpSocket.canReadLine)

lines.append(tcpSocket.readLine);

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже