Russian Qt Forum
Ноябрь 23, 2024, 22:45 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Не доходит последний пакет  (Прочитано 4066 раз)
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 сокетах - поведение одинаковое.
Причем поведение это проявляется только на машине заказчика (под виндой), на своих тестил в разных вариантах и под разными ОС  (линух, винда) такого нет.
Что можно предпринять в данном случае?
Записан
RedDog
Гость
« Ответ #1 : Ноябрь 18, 2011, 23:06 »

Еще одно, возможно важное дополнение:
void foo() работает в отдельном потоке, и по сигналу этот поток уничтожается exit(0)
Но сигналы нормально доходят до сервера, пакет формируется и отправляется.
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #2 : Ноябрь 19, 2011, 01:04 »

Закрываете сокет как по окночании?
Записан
RedDog
Гость
« Ответ #3 : Ноябрь 19, 2011, 08:31 »

НИкак не закрываю, он постоянно открыт
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #4 : Ноябрь 19, 2011, 11:10 »

Тогда как читаете?
Записан
RedDog
Гость
« Ответ #5 : Ноябрь 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Х еще и тип команды - дабы правильно распарсить потом передаваемые параметры
с самим чтением проблем не возникает... до последнего пакета
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #6 : Ноябрь 19, 2011, 15:56 »

В TCP посылки могут приходить  не целиком или наоборот слепленные вместе.
Поэтому нельзя считать, что readyRead извещает вас об 1 целом блоке. Надо убеждаться, что блок прочитан целиком (так как поток не будет ждать данные, а просто добъёт вам недостающее нулями), а после чтения посмотреть, если там есть ещё блок, то вызвать on_readyRead ещё раз.
Записан
RedDog
Гость
« Ответ #7 : Ноябрь 19, 2011, 16:41 »

Для контроля начала и конца пакета у меня и передаются лидирующий байт STX (0x05) и завершающий байт ETX (0x06).
Пакеты приходят полностью от начала и до конца, в конце слота on_dataDead() я вызываю bytesAvailable(), и она возвращает ноль. А вот последний пакет никак не доходит.
ЗЫ: Tcp я юзал только для теста, а вообще через QLocalSocket, хотя и через Tcp та же картина, причем только на компе заказчика. На моем (в винде под виртуалкой и в хостовой мандриве) нет
Записан
RedDog
Гость
« Ответ #8 : Ноябрь 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(); // добавил
}
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.12 секунд. Запросов: 23.