Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > QTcpSocket и сигнал завершения передачи данных


Автор: newbie2009 9.1.2012, 23:29
Вопрос такой. Если ли какой-то сигнал, к-ый говорит о том, что пакет полностью передан,так как пакет может передаваться и по частям.
Я в доках нашел сигнал readChannelFinished(), но что если я дальге делаю вот так, то не хочет работать:

 connect(_sok,SIGNAL(readChannelFinished()),this,SLOT(parsePacket()));
 connect(_sok, SIGNAL(readyRead()), this, SLOT(onSokReadyRead()));

в onSokReadyRead() - я собираю по частям пакет...

Или все равно придется передавать вначале число сколько байт я буду передавать, а потом уже исходя из этого считывать? или есть все таки сигнал, к-ый сгенерируется, когда ВЕСЬ пакет будет передан?

Автор: borisbn 10.1.2012, 06:22
О размере "пакета" знаете только Вы. Для Tcp/ip нет понятия "пакета". Передавать в начале длину пакета и ожидать принятое кол-во байт в readyRead() - совершенно стандартное решение, а для чего нужен сигнал readChannelFinished() - честно говоря не знаю ))) 

Автор: newbie2009 10.1.2012, 11:36
Код

  QDataStream in(_sok);
    if ( isFirstPacket ) {
        if ( _sok->bytesAvailable() < (int)sizeof(quint32) ) {
            return;
        }
        in >> packet_size;
        qDebug() << "packet size = " << packet_size;
        isFirstPacket = false;
    }

    if (_sok->bytesAvailable() < packet_size ) {
        qDebug() << "bytes avaible: " << _sok->bytesAvailable();
        return;
    }
    else {
        isFirstPacket = true;
        in >> block;
        qDebug() << block.size();
    }

Не могу понять почему размер я получаю нормально, ветки else срабатывает когда надо, а в переменную блок не заносяться данные вообще. переменную block ( QByteArray ) ? И как мне тогда считать весь мой пакет?

Автор: borisbn 10.1.2012, 11:42
Трудно сказать. Вроде ошибок не видно... Покажи, как отправляешь данные.

Автор: newbie2009 10.1.2012, 12:07
Вот так я отсылаю...
Код

QByteArray ba_file;
QDataStream out(&ba_file, QIODevice::WriteOnly);
out << xmlDoc->toByteArray();
qDebug() << client->write(ba_file);



Я конечно понимаю что можно все побайтово, т.е. вот так:
Код


    QDataStream in(_sok);
    if ( isFirstPacket ) {
        if ( _sok->bytesAvailable() < (int)sizeof(quint32) ) {
            return;
        }
        in >> packet_size;
        qDebug() << "packet size = " << packet_size;
        isFirstPacket = false;
    }

    if (_sok->bytesAvailable() < packet_size ) {
        qDebug() << "bytes avaible: " << _sok->bytesAvailable();
        return;
    }
    else {
        isFirstPacket = true;

// -----------------------------------------------------------------------
        qint8 t;
        for(int i = 0; i < packet_size; i++) {
            in >> t;
            block.append(t);
        }
        qDebug() << block.size();
// -----------------------------------------------------------------------

        emit startParse();
    }


Но это же не вариант так делать, хотя так оно и работает!=(

Автор: borisbn 10.1.2012, 13:34
Ты записываешь ф-цией сокета write, а считываешь оператором >> QDataStream'а. Записывай и считывай в/из сокета функциями write/read и не используй QDataStream вообще и будет счастье)))

P.S. Почитай http://forum.vingrad.ru/forum/topic-344912.html про DataStream'ы.

Автор: newbie2009 10.1.2012, 13:45
QDataStream в этот раз мне нужен, что отдельно еще самому не пихать размер пакета, а так он сам подсчитает и перешлет, а так заиспользова _sok->readAll() все работает правильно.
Спасибо!

Автор: borisbn 10.1.2012, 14:02
newbie2009, нехорошее решение, т.к. в следующей версии Qt они могут добавить после размера версию (к примеру), и у тебя всё поедет. Не ленись, посчитай размер (тем более, что это несложно - byteArray.size() ))) и передай его ручками.

Автор: _GRIN_ 11.1.2012, 08:38
Цитата(borisbn @  10.1.2012,  12:02 Найти цитируемый пост)
newbie2009, нехорошее решение, т.к. в следующей версии Qt они могут добавить после размера версию (к примеру), и у тебя всё поедет. 


Ну в принципе кьют предлагает решение: http://developer.qt.nokia.com/doc/qt-4.8/qdatastream.html#versioning
А вообще использование потоков очень удобно, но (имхо) всегда надо версию ставить (http://developer.qt.nokia.com/doc/qt-4.8/qdatastream.html#setVersion), что бы не зависить от версии СДК, под которой собираешь.

Хотя способ с указание размера в ручную конечно же более надёжен =)


Автор: borisbn 11.1.2012, 10:18
Цитата(_GRIN_ @  11.1.2012,  08:38 Найти цитируемый пост)
Ну в принципе кьют предлагает решение

да, но нужно не забыть перекомпилировать и передающую и принимающую сторону. А это не всегда возможно.

Автор: _GRIN_ 12.1.2012, 13:16
Цитата(borisbn @  11.1.2012,  08:18 Найти цитируемый пост)
да, но нужно не забыть перекомпилировать и передающую и принимающую сторону.

зачем?
 если одна из сторон была написана более рано (допустип передающая) и она указал у себя при создании потока версию (допустим Qt_4_5)
то при написании (переписывании) принимающей стороны (допустим под сдк 4.8) нужно просто при создании считывающего потока указать версию передающей стороны - т.е. Qt_4_5
И более старый код перекомпилировать не надо!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)