На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела *nix / gcc / Eclipse / Qt / wxWidgets / GTK+
  • При создании темы ОБЯЗАТЕЛЬНО указывайте версию тулкита / библиотеки / компилятора.
  • Перед тем как задать вопрос, сформулируйте его правильно, чтобы вас могли понять.
  • Нарушение Правил может повлечь наказание со стороны модераторов.


Полезные ссылки:
user posted image Boost по-русски
user posted image Qt по-русски
Модераторы: archimed7592
  
> QTcpSocket reconnect
    беда, есть старая прога, доставшаяся по наследству, на QT работающая на Raspberry. Клиент с Raspberry цепляется к серверу и передает данные. Раньше все это работало на старом образе Raspbian Jessy на QT 5.4, но на этой версии QT не получается доставить canbus библиотеки, по этому пришлось обновлять образ до Raspberry Buster и QT 5.11.2. В итоге получил следующий глюк, когда сервер отваливается, программа пытается переконектиться к серверу по новой

    ExpandedWrap disabled
      void Socket_thread::disconnected()
      {
        qDebug()<<"Socket Disconnecting"<<IP_HOST<<":"<<Port_HOST;
          socket->close();
          qDebug()<<"Socket try to reconnect."<<IP_HOST<<":"<<Port_HOST;
          while (!doConnect())
            {
             QThread::sleep(5);
             qDebug()<<"Socket Reconnect."<<IP_HOST<<":"<<Port_HOST;
            }
      }


    реконнект происходит, но при попытке отправить в сокет данные программа крашится. Убираю кусок реконнекта

    ExpandedWrap disabled
      qDebug()<<"Socket try to reconnect."<<IP_HOST<<":"<<Port_HOST;
          while (!doConnect())
            {
             QThread::sleep(5);
             qDebug()<<"Socket Reconnect."<<IP_HOST<<":"<<Port_HOST;
            }


    и делаю кнопку реконнект

    ExpandedWrap disabled
      connect(ui->pushButton, SIGNAL(clicked(bool)), mSocket, SLOT(doConnect()));


    И все работает. Более того, код с автоконнектом работает и на винде и на линуксе, но на Raspberry прога стабильно крашится. Может кто что то подобное встречал и может поделиться опытом.
    Сообщение отредактировано: Pit-Bul -
      Pit-Bul, попробуй такой вариант (навскидку):

      ExpandedWrap disabled
        void Socket_thread::disconnected() {
          qDebug()<<"Socket Disconnecting"<<IP_HOST<<":"<<Port_HOST;
          socket->close();
          qDebug()<<"Socket try to reconnect."<<IP_HOST<<":"<<Port_HOST;
          // поэкспериментируй с цифрой 100, как в плане уменьшения, так и в плане увеличения
          // т.к. твой код с кнопкой явно работает с горааааздо большим интервалом, видимо чем твой sleep 5
          QTimer::singleShot(100, mSocket, SLOT(doConnect()));
        }
        JoeUser, идея хорошая, но немного не то, а сам что то не понимаю как додумать. Дело в том что disconnected срабатывает один раз в момент отвала клиента, а сервер не понятно сколько времени может быть не доступен, надо либо как то в таймере проверять соединение, либо какой то сигнал, который я ищу но не могу найти )) что сервер еще в дауне. Можно конечно закостылить в основном коде таймер который будет запускаться по событию disconnected и пытаться соединиться, а при удачном соединении вырубать таймер. Но, что то мне в этом деле не нравиться. С утра на свежую голову подумаю.
          Pit-Bul, ну моя идея такова ...

          1) Твое соединение кнопарем на стопицот процентов эмулируется моим синглшотом таймера. И я в это надеюсь, и это не может быть непрекрасно.
          2) Осталось определить минимальный отрезок времени, когда после дисконнекта первый же коннект поднимет соединение с успехом.

          Протокол TCP на самом деле - костыль на костыле. И как обрабатывается твой socket->close() еще большой вопрос. Вот именно поэтому я и предлагаю поиграться с моим кодом и егошними таймаутами :)

          А вообще было бы супер где-то запустить эмуль твоего устройства (если такое можно), а в промежутке сетевого трафика запустить что-то типа Виншарка, ну и посмотреть полную картину как сервер и клиент плюются TCP-пакетами. А пока мы гадаем на кофейной гуще.
            И еще, сейчас поиграл со строчкой
            ExpandedWrap disabled
              QTimer::singleShot(100, this, SLOT(doConnect()));


            и такое ощущение что doConnect() срабатывает не в текущем экземпляре класса. Это дело еще и в отдельном потоке работает. Все таки думаю что диспетчер соединения продумывать надо и писать его в основном потоке.

            Добавлено
            Цитата JoeUser @
            1) Твое соединение кнопарем на стопицот процентов эмулируется моим синглшотом таймера. И я в это надеюсь, и это не может быть непрекрасно.
            2) Осталось определить минимальный отрезок времени, когда после дисконнекта первый же коннект поднимет соединение с успехом.



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

            Добавлено
            Цитата JoeUser @
            А вообще было бы супер где-то запустить эмуль твоего устройства (если такое можно), а в промежутке сетевого трафика запустить что-то типа Виншарка, ну и посмотреть полную картину как сервер и клиент плюются TCP-пакетами. А пока мы гадаем на кофейной гуще.


            я написал отдельно сервер, который выплевывает все что на него приходит и все что он отправляет. От него то я и узнал что реконект то случается, кслиент регистрируется на сервере, принимает от него сообщения, но когда пытается обратно отправить данные то падает. При первоначальном коннекте все работает как часики
              Цитата Pit-Bul @
              а сам что то не понимаю как додумать

              Это второй момент - архитектура твоего приложения. Каждому методу (слоту) нужно делегировать именно его полномочия.

              Пример:

              1) Разорвалось соединение - вызваем doDisconnect, а его задача (грамотно разорвать, и если надо инициировать установление):

              a) проверка, что это действительно так
              б) разорвать соединение на уровне API OS
              в) инициировать соединение (если есть состояние "надо")

              2) Установить соединение (установить соединение, если это надо - играться с таймаутами):

              a) Попробовать установить соединение со значением таймаута
              б) Если не пошло увеличить значение таймаута, и прыг в п.a)

              И еще ... прочитай про режимы работы сокетов, особенно если идет работа не по самому TCP, а по протоколам более высшего уровня, типа HTTP. Там есть одна хрень типа Keep-Alive. Она может отваливаться и через 1-2 минуты, когда связь реально утеряна. Это я все про костыли :)

              Добавлено
              Pit-Bul, не парься! Все будет хорошо! :)
                Цитата JoeUser @
                Pit-Bul, не парься! Все будет хорошо!


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

                А по сути, с архитектурой проблем не возникает, проблема в данном случае возникла с недопониманием всех этих сигналов и слотов по началу. С утра подтянул немного матчасть, почитал про QT и стало понятнее в общих чертах. Я просто в первые столкнулся с QT и немного потерялся, о спасибо JoeUser
                  Цитата Pit-Bul @
                  Я просто в первые столкнулся с QT и немного потерялся, о спасибо JoeUser

                  :victory:
                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                  0 пользователей:


                  Рейтинг@Mail.ru
                  [ Script execution time: 0,0347 ]   [ 17 queries used ]   [ Generated: 19.03.24, 06:16 GMT ]