Название: [4.3.1] Консольный обработчик входящих соединений - в чём проблема? Отправлено: SubV от Сентябрь 05, 2007, 17:35 Определены массивы соединений:
Код: struct conn В главном цикле крутится опрос по заданному порту: Код: forever Есть заготовка класса, который будет эти соединения обрабатывать: Код: class QScsConnectionHandler: public QThread При любой попытке вызова функций new_connection, т.е. write(), flush() или close программа либо падает, либо выводит сообщение вида "QObject: Cannot create children for a parent that is in a different thread. (Parent is QNativeSocketEngine(0086C628), parent's thread is QThread(00869B78), current thread is QThread(0086CAF8)". В чём проблема и как решить? Архитектуру "сигнал-слот" в данном случае использовать нежелательно по ряду причин. Название: Re: [4.3.1] Консольный обработчик входящих соединений - в чём проблема? Отправлено: WW от Сентябрь 05, 2007, 18:52 Попробуй QObject::moveToThread().
Хотя может и не сработать. Название: Re: [4.3.1] Консольный обработчик входящих соединений - в чём проблема? Отправлено: denka от Сентябрь 05, 2007, 21:07 А почему ты не воспользуешся ф-цией incomingConnection ( int socketDescriptor ) класса QTcpServer, как это сделанно в примере hreadedfortuneserver? Создавал бы сам QTcpSocket в run на основе полученого дескриптора и не было бы проблемы с парентом в другом потоке...
Название: Re: [4.3.1] Консольный обработчик входящих соединений - в чём проблема? Отправлено: SubV от Сентябрь 06, 2007, 15:51 Попробовал использовать incomingConnection и дескрипторы.
Код: class SmSrv : public QTcpServer Код: #include "smsrv.h" Теперь проблема в том, что вызов переопределенной incomingConnection() вообще не происходит. У кого-нибудь есть мысли по этому поводу? Название: Re: [4.3.1] Консольный обработчик входящих соединений - в чём проблема? Отправлено: BD от Сентябрь 07, 2007, 11:33 Не совсем понял зачем тебе нужна структура
Код: struct conn Кроме того, я так пониманию, после обработки соединения, у тебя будет снова создаваться сервер на том же порту, потому что я не вижу где ты его удаляешь // Я про первый вариант В общем, попробуй что-то типа Код: QTcpServer scs_server; Код: QTcpServer scs_server; Код: class QScsConnectionHandler: public QThread Название: Re: [4.3.1] Консольный обработчик входящих соединений - в чём проблема? Отправлено: SubV от Сентябрь 07, 2007, 16:32 Вроде бы разобрался... причина, судя по всему - странная нелюбовь QT к созданию объектов в потоке по указателю. Привожу рабочий скелет кода.
main.cpp Код: #include <QtCore/QCoreApplication> smsrv.h Код: #ifndef SMSRV_H smsrv.cpp Код: #include "smsrv.h" smсonnhandler.h Код: #ifndef SMCONNHANDLER_H smсonnhandler.cpp Код: #include "smconnhandler.h" Название: Re: [4.3.1] Консольный обработчик входящих соединений - в чём проблема? Отправлено: denka от Сентябрь 07, 2007, 17:23 Проблема не в том что Qt не любит указателию Скорей всего ты создавал новый объект так:
Код: QTcpSocket * new_connection = new QTcpSocket(this); Относительно твоего первого примера: Цитировать QObject is reentrant. Most of its non-GUI subclasses, such as QTimer, QTcpSocket, QUdpSocket, QHttp, QFtp, and QProcess, are also reentrant, making it possible to use these classes from multiple threads simultaneously. Note that these classes are designed to be created and used from within a single thread; creating an object in one thread and calling its functions from another thread is not guaranteed to work. Относительно последнего:Цитировать The child of a QObject must always be created in the thread where the parent was created. This implies, among other things, that you should never pass the QThread object (this) as the parent of an object created in the thread (since the QThread object itself was created in another thread). Т.е. зделаеш так:Код: QTcpSocket new_connection(this); Название: Re: [4.3.1] Консольный обработчик входящих соединений - в чём проблема? Отправлено: SubV от Сентябрь 07, 2007, 18:24 den'ka, я в курсе насчёт многопоточности наследников QObject. Всё дело в том, что работают оба варианта - как с созданием QTcpSocket через указатель, так и напрямую. Фишка в том, что второй вариант не ругается при выполнении.
Предупреждение "Cannot create children for a parent that is in a different thread. (Parent is QNativeSocketEngine..." выводится в консоль, поэтому вероятно, многие, кто пишет GUI просто его не наблюдали. Название: Re: [4.3.1] Консольный обработчик входящих соединений - в чём проблема? Отправлено: denka от Сентябрь 08, 2007, 08:46 Да? :) Или я тебя не правильно понял или ты говориш что есть разница между тем как создаеться объект в стеке или в куче... Тогда объясни вот что... Код:
Код: QTcpSocket new_connection(this); Код: QTcpSocket * new_connection = new QTcpSocket; Название: Re: [4.3.1] Консольный обработчик входящих соединений - в чём проблема? Отправлено: SubV от Сентябрь 10, 2007, 16:16 ...или ты говориш что есть разница между тем как создаеться объект в стеке или в куче... Тогда объясни вот что... Код: Код: QTcpSocket new_connection; // без (this); Код: QTcpSocket * new_connection = new QTcpSocket; Как раз первый вариант НЕ ругается. А второй, т.е. при выделении памяти в хипе, отрабатывает нормально, НО выводит в консоль сообщение об ошибке, приведенное выше. Никакого парента, созданного в другом потоке, я не указываю. Очевидно, это одна из "фич" QT, с которой нужно просто смириться. Еще раз скажу, что оба варианта имеют одинаковую функциональность, т.е. сокет содается, приём/передача данных работают нормально. Название: Re: [4.3.1] Консольный обработчик входящих соединений - в чём проблема? Отправлено: denka от Сентябрь 10, 2007, 16:46 Тогда объясни мне почему у меня не пишет этого сообщения? Какая может быть фича? По твоему троли каким-то образом проверяют как создаеться объект? Невериш мне так хотя бы поверь своим глазам и размышляй логически. Тебе в консоль что выводит? Что дочерный объект в разных потоках с парентом... Это как могло произойти? Только когда создаеш объект и указываеш парента из другого потока или когда сам явно устанавливаеш
Название: Re: [4.3.1] Консольный обработчик входящих соединений - в чём проблема? Отправлено: SubV от Сентябрь 10, 2007, 19:12 Вот, у человека была та же проблема. См. его отладочный лог.
http://www.qtcentre.org/forum/f-qt-programming-2/t-threaded-sever-problem-4384.html Внятного объяснения так и не нашлось. Название: Re: [4.3.1] Консольный обработчик входящих соединений - в чём проблема? Отправлено: pastor от Сентябрь 10, 2007, 22:27 Решил отписаться, но забераю свои слова назад. Добавлю лишь одно: способ размещения объекта (стек или хип) точно не причём. Сделал тестовый примерчик (в точности как у тебя), никаких сообщений не получил в консоль. Все работает как надо. имхо, проблема кроеться в другом месте. В тесте выполнял подключение к серверу 100 раз в цикле. Qt 4.2.3/4.3.0 VS2005+SP1. Сегодня качну 4.3.1 проверю на ней, но думаю результат останется прежним.
Попробуйте пройтись дебагером в самой Qt и посмотреть что к чему. Название: Re: [4.3.1] Консольный обработчик входящих соединений - в чём проблема? Отправлено: SubV от Сентябрь 11, 2007, 14:50 У меня QT 4.2.3/4.3.0/4.3.1, VS2003 + SP1.
Неужели дело в компиляторе? Впрочем, создание сокета в стеке на данный момент меня устраивает. Так что проехали.. Название: Re: [4.3.1] Консольный обработчик входящих соединений - в чём проблема? Отправлено: denka от Сентябрь 11, 2007, 15:22 Я тут покапался в исходниках Qt. Вот тебе последовательность вызовов конструкторов для QTcpSocket с их исходниками...
Код: QTcpSocket::QTcpSocket(QObject *parent) как видиш меседж идет из ф-ции check_parent_thread и только в том случае если parent не равен 0 он выводиться :) З.Ы. Думаю в твоем случае это не компилятор, скорей погода или магнитная буря... Тут нужен хороший танец с бубнами ;) Название: Re: [4.3.1] Консольный обработчик входящих соединений - в чём проблема? Отправлено: pastor от Сентябрь 11, 2007, 17:15 Проверил на Qt 4.3.1. Всё работает нормально.
BWT: Удалось воспроизвести вывод в консоль лишь в том случае, когда был указан парент: Цитировать QObject: Cannot create children for a parent that is in a different thread. (Parent is SmConnHandler(01AAA1F8), parent's thread is QThread(003A2CC0), current thread is SmConnHandler(01AAA1F8) имхо, это то про что говорил den'ka в своих постах, в том числе и последнем. |