![]() |
|
![]() ![]() ![]() |
|
SwordOfDeath |
|
||||
Шустрый ![]() Профиль Группа: Участник Сообщений: 130 Регистрация: 16.10.2007 Репутация: нет Всего: нет |
Всем привет
Столкнулся с проблемой... В примере Threaded Fortune Server не описан процесс обмена данными... они только посылаются и сразу же закрывается поток (что очень странно, смысла в многопоточности для такой проги ноль...) Я пытался переделать и совместить Threaded Fortune Server c Loopback... И уже разобрался что в потоке нужно запустить event loop через exec() но натолкнулся на проблему. Как я понял если для QTcpSocket указать socketDescriptor то он начинает отрабатывать сообщения этого сокета... Так вот если я в потоке пытаюсь поставить setSocketDescriptor(socketDescriptor) то ругается в окно вывода проги:
А если переношу QTcpSocket в новосозданный поток (thread->tcpServerConnection.moveToThread(thread)), причем ругается в exec():
В общем не понимаю я всей этой архитектуры... А Qt написали такие скудные примеры =\ Помогите кто чем сможет... На данный момент это простенький чат пишется для тестирования... UPD: Processing Qt 4.5 moveToThread() или метод “Мюнхгаузена” Это сообщение отредактировал(а) SwordOfDeath - 19.7.2009, 11:37 |
||||
|
|||||
null56 |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 6 Всего: 12 |
попробую догадаться, но не совсем понял, где что создается
1) tcpServerConnection - это объект переменная член класса? создается где? в функции run() или нет? 2) если tcpServerConnection создается в функции run, то ты НЕ можешь делать вот так из основного потока
Так как за объект класса QTcpSocket отвечает дочерний поток, ты должен ему передавать дескриптор сокета, средствами сигналов - слотов или посылая сообщения фунцией postEvent (sendEvent), где можешь передавать сам файловый дескриптор 3) По поводу этого я не уверен,
а именно, где ты создаешь объект сокета... могу лишь предположить, что ты назначаешь родителя объекту tcpServerConnection, что делать, при использовании moveToThread НЕЛЬЗЯ 4) Хорошо бы привезти код, не весь, а только концептульный твоей проблеме, было бы нагляднее Это сообщение отредактировал(а) null56 - 19.7.2009, 23:04 |
||||
|
|||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 81 Всего: 91 |
Я бы не рекомендовал использовать не свои классы с методом moveToThread. Этот метод за раз переносит только один объект, если при этом объект создает внутри себя или пытается использовать другие QObject'ы, то без их переноса возникнет проблема.
|
|||
|
||||
SwordOfDeath |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 130 Регистрация: 16.10.2007 Репутация: нет Всего: нет |
Таксь последовал вашим замечаниям по поводу moveToThread, и теперь создаю tcpServerConnection в run()... Таким образом мне уже не нужно его куда либо переносить.
Покопавшись разобрался почему ругается в exec() созданного потока; Я связываю сигнал из потока с слотом из главного потока:
В мануале написано что Сигнал-Слот без проблем работает между потоками... А тут вот грабли... Или может это грабли с передаваемыми данными? Как правильно это делать? |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 81 Всего: 91 |
Проверь не пишется ли в консоль что-то связанное с QByteArray и qRegisterMetatype.
|
|||
|
||||
SwordOfDeath |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 130 Регистрация: 16.10.2007 Репутация: нет Всего: нет |
Вот полный вывод начиная от старта и заканчивая закрытием:
Это сообщение отредактировал(а) SwordOfDeath - 20.7.2009, 12:12 |
|||
|
||||
null56 |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 6 Всего: 12 |
я имел в виду исходный код твоей программы
это происходит потому, что программа закрывается до того, как завершатся дочерние потоки... подождать надо завершения |
||||
|
|||||
SwordOfDeath |
|
||||
Шустрый ![]() Профиль Группа: Участник Сообщений: 130 Регистрация: 16.10.2007 Репутация: нет Всего: нет |
Привожу частичный код
Как видно он ничем не отличается от примеров Qt... кроме как запуском eventloop'a и связыванием сигнал-слота в разных потоках. UPD: Двигаюсь дальше... Ошибку вызывает не сам Сигнал-Слот и не его параметры... А код который описан в слоте... Так как будто этот код вызывается прямо в контексте потока который сгенерил сигнал... Указание Qt::QueuedConnection результата не дали... Это сообщение отредактировал(а) SwordOfDeath - 20.7.2009, 19:33 |
||||
|
|||||
null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 6 Всего: 12 |
Я набил пример тебе маленький, где использую ТВОЙ код...
Сервер висит в ожидании, при поступлении нового подключения создает объект нити, передавая туда дескриптор. Клиент, коннектится к серверу, как только подлючается в слоте onConnected посылает строку серверу... Все работает без проблем... цепляй прикрепленный файл, там отдельно собирешь клиента и сервера, запустишь и посмотришь, правильно ли я понял твою идею и твой вопрос Присоединённый файл ( Кол-во скачиваний: 37 ) ![]() |
|||
|
||||
null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 6 Всего: 12 |
ЗЫ: естетсвенно, чтобы не было
ты сам должен позаботиться о том, чтобы завершить eventloop и дочерний поток, перед тем, как завершится основной поток Присоединённый файл ( Кол-во скачиваний: 42 ) ![]() |
|||
|
||||
SwordOfDeath |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 130 Регистрация: 16.10.2007 Репутация: нет Всего: нет |
Спасибо огромное за помощь... Но кажется это не решит моей проблемы...
Так как вы в parseMessage(int value, QByteArray msg) вызываете qDebug() которому не важно в каком потоке он вызван... Мне же в этой функции нужно работать с данными и вызывать функции главного потока... |
|||
|
||||
null56 |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 6 Всего: 12 |
Я не понимаю, приведи пример, того, чего ты хочешь
слот будет обрабатываться в основном потоке, так как он создан вместе с оъектом ChatHostServer в основном потоке Добавлено через 3 минуты и 53 секунды
приведи пример кода в слоте |
||||
|
|||||
SwordOfDeath |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 130 Регистрация: 16.10.2007 Репутация: нет Всего: нет |
Продвинулся дальше...
При прихождении данных я передаю сообщение в основной поток... где его обрабатываю и отсылаю ответ назад в поток который прислал данные... и уже там слот:
Вот он то и создает ошибку... Чувствую себя паршиво что не отдебажил все как положено до самого конца =\ Также эту же ошибку вызывает добавление tcpServerConnection->write(tcpServerConnection->readAll()); в слот void ChatHostThread::incomingData() Проверил на вашем примере... Та же ошибка при попыке отправки сообщения с сервера клиенту... Это сообщение отредактировал(а) SwordOfDeath - 20.7.2009, 21:34 |
|||
|
||||
null56 |
|
||||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 6 Всего: 12 |
НИИИИИИИЗЗЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ, написал же чуть выше про подобное...
Объект класса QTcpSocket обслуживается дочерней нитью и лезть к этому объекту из другой нити, нИИИИИИИИзЯ... Можно передать эти данные дочерней ните, которая уже будет отсылать их твоему объекту сокету... примерно так дополню твой класс ChatHostThread
Функция run()
Далее унаследуй класс от QTcpSocket и в функции run создавай уже его, чтобы определить этот недостающий слот... например
Переменную член класса так же делаешь своим TcpSocket и в функции run создаешь его же...
Теперь через такую Ж мы получили следующее: вызов функции sendMessage(QByteArray message) (даже если это слот) сгенерит сигнал, слот которого обработается в дочернем потоке объекта нашего класса TcpSocket во... ) Это сообщение отредактировал(а) null56 - 20.7.2009, 21:45 |
||||||||
|
|||||||||
SwordOfDeath |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 130 Регистрация: 16.10.2007 Репутация: нет Всего: нет |
Так я так и делаю!...
Не лезу я к этому объекту из другой нити... Я все через Сигнал-Слоты гоняю... И опять же проблему можно повторить и в вашем примере: Добавив в ChatHostThread :: incomingData()
Хм.. но данные отправляются... |
|||
|
||||
null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 6 Всего: 12 |
это у тебя слот??? |
|||
|
||||
SwordOfDeath |
|
||||||||
Шустрый ![]() Профиль Группа: Участник Сообщений: 130 Регистрация: 16.10.2007 Репутация: нет Всего: нет |
chathostthread.h
chathostthread.cpp
chathostserver.h
chathostserver.cpp
|
||||||||
|
|||||||||
null56 |
|
||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 6 Всего: 12 |
Значит смотри, в чем разница, что я написал и ты
У тебя есть класс со слотом
Этот класс ты создаешь в основном потоке (если я ничего не пропустил), А ЗНАЧИТ твой слот sendMessage(QByteArray) после генерации сигнала sendMessage(QByteArray), будет так же обрабатываться в ОСНОВНОМ потоке
А что же это значит: что твой слот будет вызывать функцию write у объекта QTcpSocket в основном потоке... чего делать, похоже нельзя ) так как за объект отвечает дочерний поток
Я прикрепил модифицированный пример, где уже сервер шлет клиенту по таймеру сообщения, все работает и не жалуется Каждые три секунды ты будешь получать от сервера сообщение Присоединённый файл ( Кол-во скачиваний: 89 ) ![]() |
||||||
|
|||||||
SwordOfDeath |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 130 Регистрация: 16.10.2007 Репутация: нет Всего: нет |
Огромное спасибо... Наконец дошло...
Блин сделали красивую обвертку QThread а она вовсе некрасивая... Только запутывает... Реально потерялся что чему пренадлежит... Все понял... Исправлюсь!... |
|||
|
||||
null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 6 Всего: 12 |
в твоем случае тебе бы помог "метод Мюнхгаузена", хорошо описанный SABROG
только надо было сделать это для объекта thread целиком
тогда бы твой слот через сигнал обрабатывался в дочернем потоке и ошибок бы не было |
|||
|
||||
SwordOfDeath |
|
||||
Шустрый ![]() Профиль Группа: Участник Сообщений: 130 Регистрация: 16.10.2007 Репутация: нет Всего: нет |
Когда юзал
то ругалось так:
Убрал из конструктора указание parent и все пучком = ) Спаси огромное за реальную помощь... Мне нравится этот форум тем что здесь действительно помогают... Даже если вопросы глупые... как у меня например... Ведь мог бы и сам не поленится отдебажить и разобратся в чем проблема... Просто проснулся как-то и решил попрограмить, настрочил настрочил без дебага... а потом думаю как бы его розгребсти то ) |
||||
|
|||||
ikss |
|
|||
Новичок Профиль Группа: Участник Сообщений: 1 Регистрация: 22.1.2011 Репутация: нет Всего: нет |
А такой не стандартный вопрос по теме, пробую поставить 85 порт, по нему ни как не получается завязатся, можно ли организовать связь через какой-то стандартный порт, вот открытые порты какие я вчера просканировал
21 открыт ftp 22 открыт ssh 25 открыт smtp 53 открыт domain 80 открыт www 85 открыт неизвестно 110 открыт pop3 143 открыт imap2 443 открыт https по QHttp нормально получается инфа через 85 порт, а когда ставлю его на connectToHost ни чего не происходит инфа не идет ------------------------------------------ Да не посмотрел на год темы =) но может кто подскажет всеж??? Это сообщение отредактировал(а) ikss - 22.1.2011, 15:16 |
|||
|
||||
![]() ![]() ![]() |
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets" | |
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |