Название: QLocalSocket проблема с многопоточностью Отправлено: JAkutenshi от Декабрь 10, 2014, 12:42 Здравствуйте!
Проблема следующая: есть написанный и отлаженный клиент, а есть сервер, у которого проблемы с многопоточностью ибо все моих рук дело. Что хочется: чтобы каждый клиент обрабатывался в QThread::run(). В чем проблема: QObject: Cannot create children for a parent that is in a different thread. (Parent is QLocalSocket(0x758fa8), parent's thread is QThread(0x8216b0), current thread is NewConnectionThread(0x7581f8) Код run-a: Код: void NewConnectionThread::run() Причину, кажется, понимаю: clientSocket->write(response) рискует просуществовать дольше своего потока. Но при этом не очень понимаю, как исправить без костылей. Еще есть второй момент, в clientSocket->waitForReadyRead(1). Судя по докам, когда данные готовы к чтению, он не дожидаясь дефолтного счетчика (30000 мс) возвращает готовность. Но не тут-то было и в этой вариации оно ждет полностью счетчик. В абсолютно таком же run-e, разве-что в реализации с гуи (вешепредставленны ран из консоли, но мне кажется это не должно влиять на выполнение метода Оо), оно сразу выходит из ожидания. ЧЯДНТ? Немного подумав, я вспомнил, что клиент читал малость по-другому и ожидал через сигнал readReady(). Ну, ладно, делаем, объявляю слот read() у потока и в итоге: Код: NewConnectionThread::NewConnectionThread(LocalServer* parentLocalServerRef, Казалось бы, все распрекрасно, и ошибок нет и читает быстро. Вот только многопоточности почему-то нету... Т.е., нету ее потому что run() заканчивается после коннекта? И потом read() выполняется в основном потоке, как я понял, судя по дебагу (там всегда 1 поток был на обработку клиента, менялся только айдишник). Ниже, весь код сервера: Код: _________localserver.h Слезливо прошу о помощи, ибо дедлайн буквально завтра, впереди корба и соап, а на пайпы я потратил по таким мелочам больше 2х ночей и моральных сил сделать нормально без костылей уже нету. Спасибо! Название: Re: QLocalSocket проблема с многопоточностью Отправлено: Пантер от Декабрь 10, 2014, 12:45 А нужна ли тут многопоточность? Работа с сокетами ассинхронна, главное, работать через сигналы/слоты.
nextPendingConnection нужно вызывать в том же потоке, в котором живет сервер. Название: Re: QLocalSocket проблема с многопоточностью Отправлено: JAkutenshi от Декабрь 10, 2014, 12:48 Да, многопоточность с методами синхронизации нужны как условие лабы. Да и почему нет? Если каждый клиент будет ждать, пока будут обработаны предыдущие - как минимум не выполняется условие РВС о прозрачности :). Поэтому каждый клиент должен обрабатываться при подключении отдельным потоком.
Название: Re: QLocalSocket проблема с многопоточностью Отправлено: Пантер от Декабрь 10, 2014, 12:51 Не обязательно. Ассинхронка же.
В общем, тебе нельзя никакие блокирующие методы юзать типа waitForReadyRead. Все на сигналах/слотах (сигналы readyRead, bytesWritten). Название: Re: QLocalSocket проблема с многопоточностью Отправлено: Пантер от Декабрь 10, 2014, 12:53 Лови мое тестовое задание на одну из вакансий (https://gitlab.com/panter_dsd/clientserver/tree/master/src/Server). Там достаточно просто реализована многопоточная работа с клиентами. Думаю, разобраться не составит сложности.
Название: Re: QLocalSocket проблема с многопоточностью Отправлено: JAkutenshi от Декабрь 10, 2014, 12:58 Можете пожалуйста пояснить про синхронность/ассинхронность? Несколько путаю понятия. Ну, разве что имею в голове пример udp/tcp как пример ассинхронного/синхронного протоколов взаимодействия по сети, но эти понятия зависят от контекста, если не ошибаюсь... Что Вы подразумеваете под этим здесь?
Т.е. вариант с сигналом readReady() - таки правильное решение было? Спасибо большое за пример! Разберусь. Название: Re: QLocalSocket проблема с многопоточностью Отправлено: Пантер от Декабрь 10, 2014, 13:00 Ну, смотри, подключились к тебе 100 клиентов, но данные к тебе попадают ассинхронно - то есть, ты не должен сразу 100 клиентов читать и отвечать им. Как только пришла порция данных от клиента, обработчик этого клиента читает данные и что-то с ними делает.
Название: Re: QLocalSocket проблема с многопоточностью Отправлено: JAkutenshi от Декабрь 10, 2014, 14:01 Простите, можно еще?
В разных потоках я создаю соединения и помещаю их в ожидание данных. Данные получаются ассинхронно, да. Могут придти в любое время в любом порядке. Но что мешает их ассинхронно принимать и отвечать? По готовности соединения начать чтение и ответ... И как? И что с той ошибкой ны clientSocket->write(response)? Тем было в сети много с этим но как решить проблему не очень понял. Что то с moveToThread я так понимаю, но в голове с этим каша. Название: Re: QLocalSocket проблема с многопоточностью Отправлено: Пантер от Декабрь 10, 2014, 14:07 Сокеты ты создаешь в главном потоке. делаешь свой класс, который будет работать с конкретным сокетом и помещаешь его в поток. В классе ты на readyRead читаешь данные и работаешь с ними (при создании не забудь вычитать то, что уже пришло от клиента). Посмотри внимательно пример, который я привел - там все просто.
Название: Re: QLocalSocket проблема с многопоточностью Отправлено: JAkutenshi от Декабрь 10, 2014, 15:58 Я посмотрел Ваш проект и возник вопрос:
ClientConnection *clientConnection = new ClientConnection (socket); QThread *thread = Core::moveToThread (clientConnection); Как мы тред помещаем в QObject? Можете пояснить это место? Название: Re: QLocalSocket проблема с многопоточностью Отправлено: Пантер от Декабрь 10, 2014, 16:03 Мы QObject помещаем в тред.
Код
Название: Re: QLocalSocket проблема с многопоточностью Отправлено: JAkutenshi от Декабрь 10, 2014, 16:15 Читаю док по QObject и там только вариация : void moveToThread(QThread* targetThread)
ps: qt5.3 если что. И еще не вижу, что thread стартует Оо Название: Re: QLocalSocket проблема с многопоточностью Отправлено: Пантер от Декабрь 10, 2014, 16:16 Читаю док по QObject и там только вариация : void moveToThread(QThread* targetThread) Ну, object->moveToThread (thread);. Я просто вынес это в отдельную функцию.Название: Re: QLocalSocket проблема с многопоточностью Отправлено: JAkutenshi от Декабрь 10, 2014, 16:50 Все получилось, спасибо большое!
|