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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Многопоточная работа с сокетами  (Прочитано 3517 раз)
Golikov
Гость
« : Июнь 09, 2016, 11:04 »

Всем привет!

Есть класс в котором два QTcpSocket и один QTimer.

Код:
StateTimer = new QTimer(this);
ControlSock = new QTcpSocket(this);
StatSock = new QTcpSocket(this);

для них внутри класса определены 5 слотов и все они подключены вот так

Код:
QObject::connect(StateTimer, SIGNAL(timeout()), this, SLOT(Timer_slot()));
QObject::connect(ControlSock, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(ControlSockStateChange_slot(QAbstractSocket::SocketState)));
QObject::connect(StatSock, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(StatSockStateChange_slot(QAbstractSocket::SocketState)));
QObject::connect(ControlSock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(ControlSockError_slot(QAbstractSocket::SocketError)));
QObject::connect(StatSock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(StatSockError_slot(QAbstractSocket::SocketError)));

во всех слотах вызывается одна и та же функция. В этой функции я  сделал
Код:
counter++;
qDebug() << "call: " << (int) QThread::currentThreadId();
qDebug() << "counter: " <<counter;
....
counter--;
return;

В моем идеальном мире что-бы не происходило с сетью и таймером функция должна всегда писать "counter: 1". Однако при разрыве соединения (физически вырвали кабель) когда рушатся 2 сокета разом, и генерят кроме 2 смен состояний еще и ошибки, происходит 6 вызовов функции. Но не последовательно как я предполагал, а параллельно!
я получаю запись

Цитировать
call: 9600
counter: 1

call: 9600
counter: 2

call: 9600
counter: 3

call: 9600
counter: 4

call: 9600
counter: 5

Объясните люди добрые какого же фига происходит? Как может происходит вызов функции из одного потока по событиям несколько раз? Внутри функции естественно никаких обработчиков очереди сообщений не дергаю.

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




Записан
qate
Супер
******
Offline Offline

Сообщений: 1177


Просмотр профиля
« Ответ #1 : Июнь 09, 2016, 12:20 »

Объясните люди добрые какого же фига происходит?

рабочий проект организуешь, может и подскажем, а так гадать не интересно
Записан
Golikov
Гость
« Ответ #2 : Июнь 09, 2016, 12:32 »

И как его организовать? Эта штука общается по сети с кастомной железкой....
могу выложить файлы виндовые, не жалко. Но как его вам запустить? И куда его выложить?

Как работает QTimer, QTcpSocke физически? Как я себе представляю у них есть какое-то ядро, которое работает в отдельном потоке и по результатам работы этого ядра сами классы выдают сигналы в том потоке в каком они живут? То есть в любом случае это будут сообщения в очереди? Поток ядра же не может дергать функции напрямую, ведь правда?
Записан
qate
Супер
******
Offline Offline

Сообщений: 1177


Просмотр профиля
« Ответ #3 : Июнь 09, 2016, 13:35 »

И как его организовать?

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

Записан
Golikov
Гость
« Ответ #4 : Июнь 09, 2016, 14:29 »

Вот файлики проекта
Записан
Golikov
Гость
« Ответ #5 : Июнь 09, 2016, 14:32 »

и вот последний.


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

сейчас в проект дебуга напихано можно глядеть что там как происходит.

Интересует блок соединений в файле oscstcpcontrol.cpp, если их делать по умолчанию то будет такая канетель как описывал.
Записан
qate
Супер
******
Offline Offline

Сообщений: 1177


Просмотр профиля
« Ответ #6 : Июнь 09, 2016, 15:37 »

OSCSTcpControl MyControl живет в потоке ControlThread, а OSCSTcpControl::StateTimer в основном - наверно это не так задумывалось ?
Записан
Golikov
Гость
« Ответ #7 : Июнь 09, 2016, 15:54 »

QTimer создается в классе OSCSTcpControl как new QTimer(this);
следовательно он потомок, и когда я вызываю moveToHread для родителя, они все хором переезжают в новый thread. Разве не так?
Записан
Golikov
Гость
« Ответ #8 : Июнь 09, 2016, 16:59 »

Ну что же, я нашел в чем была загадка....

Естественное единственным объяснением такого поведение было вызов функции разбора очереди сообщений. Я ее не вызывал, но вот методы QTcpSocket, а вернее даже его абстрактного родителя это делали. Как только я вызывал у себя ControlSock->abort(); или ControlSock->disconnectFromHost(); а может быть и ControlSock->state(); где то внутри прокручивалась очередь сообщений, и происходил вызов следующего сигнала с повторным входом в имеющуюся функцию...

Остался вопрос про то меняется ли тип connect после moveToThread или это вообще вычисляется в момент вызова.

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


Это все не верно, все проще. Ошибка сокета вызывала разрыв соединения, но не для одного, а для обоих сокетов, а разрыв соединения вызывал сигнал который приводил в ту же функцию.
Разбор очереди сообщений там тоже есть, иначе было бы только 3 вызова, ошибка от любого сокета и дальше 2 вызова изменения состояния, однако происходит 4 вызова, но надо убедиться что 4 вызов тоже ошибка, а не какие то 2 изменения состояния....
« Последнее редактирование: Июнь 09, 2016, 18:20 от Golikov » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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