Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Ввод/Вывод, Сеть. Межпроцессное взаимодействие _ QTcpSocket и синхронный протокол

Автор: canavar 26.3.2009, 22:54

Все доброго вечера.

Непонятно, как решать вот такую проблему. Существует синхронный протокол передачи уровня приложения. Я посылаю команду, жду - приходит ответ. В простом режиме работы с QTcpSocket все понятно: создали, соединили сигналы со слотами. Отправляем данные, когда нам отвечают - вызывается слот OnReadyRead() и дальше делаем с данными все что хотим.

Есть желание сделать метод, который будет возвращать весь ответ, то типа того:

QStringList getAnswer(QString &cmd);

То есть я вызываю этот метод с необходимой командой в параметре, а на выходе получаю список строк, который пришел от сервера.

Такое вообще реально реализовать?

Заранее спасибо.

Автор: kwisp 26.3.2009, 23:16

canavar,
можно. элементарное из ассистента что на ум пришло это qWait(int msec) можно использовать.

Автор: Litkevich Yuriy 27.3.2009, 1:43

Цитата(canavar @ 27.3.2009, 1:54) *
То есть я вызываю этот метод с необходимой командой в параметре, а на выходе получаю список строк, который пришел от сервера.
я с сеткой не работал, но механизм в синхронных комуникациях примерно один и тот же:
создаешь доппоток и реализуешь в нем свой протокол. Делаешь слот типа sendCommand и сигнал ready.
Вместо getAnswer используешь sendCommand, ну а по сигналу ready читаешь уже все данные.

Автор: igor_bogomolov 27.3.2009, 3:20

По поводу qWait(int msec) ничего сказать не могу, никогда ее не использовал. Хотя в ассистенте написано, что Gui и сетевой интерфейс она не блокирует. Правильно ли это тянуть с собой в приложении функционал из QTestLib?

Мне не совсем понятно, что значит "весь ответ". У Вас есть критерий, по которомы Вы можете определить, что все ожидаемые данные получены? Или единственным критерием будет являться то, что в соккет какое-то время данные не поступают.

В любом случае, я вижу только два пути. Первое - организовать все через блокирующую функцию waitForReadyRead(int msecs), т.е. примерно так

Раскрывающийся текст
const QStringList & getAnswer(const QString &cmd) {
    socket.write(qPrintable(cmd));
    socket.flush();

    QStringList strlist;
    forever {
        if(waitForReadyRead(1000)) {
            strlist << socket.read(socket.bytesAvailable());
        } else break;
    }
    return strlist;
}

Что, как сами понимаете, делать не стОит, т.к. Gui будет заблокированно на неопределенное время. (Хотя всегда можно добавить qApp->processEvents(). Но мне такой подход не нравится.)

Во втором случае - это, как уже предлогалось, сделать все это в дочернем потоке. Правда структура проекта будет несколько иной, что Вы изначально хотели.

Раскрывающийся текст
void ThreadSocket::run()
{
    QStringList strlist;
    emit SendServer("cmd"); // отправляем данные для записи в соккет
    QMutexLocker locker(&mutex);
    forever {
        if ( cond.wait(&mutex, 1000) ) {
            strlist << DataIn; //  DataIn - данные полученные по соккету, в обработчике события readyRead()
            DataIn.clear();
        } else break;
    }
    emit sendData(strlist); // отправляем полученные данные.
}

P.S. Коды не компилил. Надеюсь сильно нигде не облажался :rolleyes:

Автор: canavar 28.3.2009, 0:12

"Весь ответ" -- имеется ввиду следущее: читаем данные, пока не будет строки, вида: "xxx end", где xxx - код ответа.

Спасибо огромное! Я сделал через отдельный поток, то есть я пошел по второму пути. :)

Еще раз спасибо.

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)