Russian Qt Forum

Qt => Работа с сетью => Тема начата: RedDog от Ноябрь 18, 2011, 22:53



Название: Не доходит последний пакет
Отправлено: RedDog от Ноябрь 18, 2011, 22:53
Суть такая:
Есть некий объект, который выполняет свою работу и при этом промежуточные результаты высылает в виде сигналов:

Код
C++ (Qt)
void foo()
{
   while(true)
   {
       if (....)
           emit Signal1(QString ID, QString param);
      else if (....)
           emit Signal2(QString ID, qint64 param1);
   // etc
       if (blabla)
           break;
   }
   emit EndOfWork(QString ID, QString param3);
}

Есть QLocalServer который соединен своими слотами с вышеозначенным объектом, и все нормально до него доходит.
Он обрабатывает сигнал, формирует пакет для отправки и отправляет клиенту.
Общий код формирования пакетов, для каждого из сигналов он свой,но принцип один:
Код
C++ (Qt)
void MyLocalServer::on_Signal1(QString ID, QString param)
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_6);
    out << (qint8)STX; // 0x05
    out << ID;
    out << param;
    out << (qint8)ETX; // 0x06
    out.device()->seek(0);
    serverSocket->write(block);
    serverSocket->waitForBytesWritten();
}
К серверу подключается локальный клиент,который получает эти пакеты и обрабатывает.
Все пакеты нормально доходят до клиента, кроме последнего, который формируется на сигнал
Код:
emit EndOfWork(QString ID);
Однако, если послать после него еще какой либо пакет, то пакет сформированный на EndOfWork доходит нормально.
Получается что последний пакет где то "застревает" и его надо протолкнуть (flush()) использовал - не помогло.
Тоже самое делал и на Tcp сокетах - поведение одинаковое.
Причем поведение это проявляется только на машине заказчика (под виндой), на своих тестил в разных вариантах и под разными ОС  (линух, винда) такого нет.
Что можно предпринять в данном случае?


Название: Re: Не доходит последний пакет
Отправлено: RedDog от Ноябрь 18, 2011, 23:06
Еще одно, возможно важное дополнение:
void foo() работает в отдельном потоке, и по сигналу этот поток уничтожается exit(0)
Но сигналы нормально доходят до сервера, пакет формируется и отправляется.


Название: Re: Не доходит последний пакет
Отправлено: LisandreL от Ноябрь 19, 2011, 01:04
Закрываете сокет как по окночании?


Название: Re: Не доходит последний пакет
Отправлено: RedDog от Ноябрь 19, 2011, 08:31
НИкак не закрываю, он постоянно открыт


Название: Re: Не доходит последний пакет
Отправлено: LisandreL от Ноябрь 19, 2011, 11:10
Тогда как читаете?


Название: Re: Не доходит последний пакет
Отправлено: RedDog от Ноябрь 19, 2011, 13:48
на сигнал readyRead сокета в клиенте...
Код
C++ (Qt)
void ClientApp::on_readyRead()
{
    QDataStream in(clientSocket);
    in.setVersion(QDataStream::Qt_4_6);
    qint8 STX_Code, ETX_Code;
    QString ID;
    QString param;
    in>>STX_Code;
    in>>ID;
    in>>param;
    in>>ETX_Code;
}
 
это псевдокод, ибо в реальном еще добавлено после STХ еще и тип команды - дабы правильно распарсить потом передаваемые параметры
с самим чтением проблем не возникает... до последнего пакета


Название: Re: Не доходит последний пакет
Отправлено: LisandreL от Ноябрь 19, 2011, 15:56
В TCP посылки могут приходить  не целиком или наоборот слепленные вместе.
Поэтому нельзя считать, что readyRead извещает вас об 1 целом блоке. Надо убеждаться, что блок прочитан целиком (так как поток не будет ждать данные, а просто добъёт вам недостающее нулями), а после чтения посмотреть, если там есть ещё блок, то вызвать on_readyRead ещё раз.


Название: Re: Не доходит последний пакет
Отправлено: RedDog от Ноябрь 19, 2011, 16:41
Для контроля начала и конца пакета у меня и передаются лидирующий байт STX (0x05) и завершающий байт ETX (0x06).
Пакеты приходят полностью от начала и до конца, в конце слота on_dataDead() я вызываю bytesAvailable(), и она возвращает ноль. А вот последний пакет никак не доходит.
ЗЫ: Tcp я юзал только для теста, а вообще через QLocalSocket, хотя и через Tcp та же картина, причем только на компе заказчика. На моем (в винде под виртуалкой и в хостовой мандриве) нет


Название: Re: Не доходит последний пакет
Отправлено: RedDog от Ноябрь 21, 2011, 12:48
похоже ошибка была в том, что при предпоследнем пакете срабатывал сигнал redyRead у сокета, в этот же момент в буфер загонялся последний, а вычитывался из буфера только предпоследний, а последний так и оставался висеть в буфере, до прихода следующего пакета, а т.к. следующий мог быть не скоро, то это было визуально заметно ("зависание" последнего значения).
Добавил рекурсию в redyRead сокета:

Код
C++ (Qt)
void ClientApp::on_readyRead()
{
    QDataStream in(clientSocket);
    in.setVersion(QDataStream::Qt_4_6);
    qint8 STX_Code, ETX_Code;
    QString ID;
    QString param;
    in>>STX_Code;
    in>>ID;
    in>>param;
    in>>ETX_Code;
    if (clientSocket->bytesAvailable() > 0)
        on_readyRead(); // добавил
}