Класс ClientSocket наследует QTcpSocket и инкапсулирует состояние одного клиента.

01 ClientSocket::ClientSocket(QObject *parent)

02 : QTcpSocket(parent)

03 {

04 connect(this, SIGNAL(readyRead()), this, SLOT(readClient()));

05 connect(this, SIGNAL(disconnected()), this, SLOT(deleteLater()));

06 nextBlockSize = 0;

07 }

В конструкторе мы устанавливаем необходимые соединения сигнал—слот и задаем переменной nextBlockSize значение 0, свидетельствующее о том, что мы еще не знаем размер посланного клиентом блока.

Сигнал disconnected() подсоединяется к функции deleteLater(), которая наследуется от класса QObject, и удаляет объект после возврата управления в цикл обработки событий Qt. Это обеспечивает удаление объекта ClientSocket после закрытия сокетного соединения.

01 void ClientSocket::readClient()

02 {

03 QDataStream in(this);

04 in.setVersion(QDataStream::Qt_4_1);

05 if (nextBlockSize == 0) {

06 if (bytesAvailable() < sizeof(quint16))

07 return;

08 in >> nextBlockSize;

09 }

10 if (bytesAvailable() < nextBlockSize)

11 return;

12 quint8 requestType;

13 QString from;

14 QString to;

15 QDate date;

16 QTime time;

17 quint8 flag;

18 in >> requestType;

19 if (requestType == 'S') {

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 }

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

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