LINUX.ORG.RU

QTcpSocket и многопоточность

 , ,


0

2

В Qt не разрешено QTcpSocket бегать по тредам, предлагается создавать новый QTcpSocket и в него запихивать дескриптор. Так вот, а если мне надо, что бы этот сокет побывал по очереди в разных тредах, то как поступать в такой ситуации? Возможно ли как то удалить объект QTcpSocket не закрывая дескриптор? Чтобы в каждом треде по новому QTcpSocket + setSocketDescriptor и погнали наши городских? Не могу нагуглить, как такие вопросы решаются.

★★★

QObject::moveToThread()

но проще будет не использовать QtNetwork и работать с сокетами напрямую

Harald ★★★★★
()
Ответ на: комментарий от slovazap

Это значит, что в Qt сокеты приколачиваются к треду. Лечится только если тред который породил этот сокет, через moveToThread перепихает его в другой. В принципе вменяемый в какой-то мере вариант, но может кто ещё каких вариантов подкинет.

vova7890 ★★★
() автор топика
Ответ на: комментарий от vova7890

Это значит, что в Qt сокеты приколачиваются к треду. Лечится только если тред который породил этот сокет, через moveToThread перепихает его в другой. В принципе вменяемый в какой-то мере вариант, но может кто ещё каких вариантов подкинет.

Сокеты никуда не приколачиваются, они просто не thread-safe что абсолютно нормально. И не путай семантику владения и семантику доступа.

slovazap ★★★★★
()
Ответ на: комментарий от vova7890

а что там принципиально могло поменяться?

Harald ★★★★★
()
Ответ на: комментарий от slovazap

они просто не thread-safe что абсолютно нормально

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

Harald ★★★★★
()
Ответ на: комментарий от slovazap

QObject: Cannot create children for a parent that is in a different thread. (Parent is QNativeSocketEngine(0x5555557cebb0), parent's thread is QThread(0x5555557b1fd0), current thread is QThread(0x5555557cfdf0)

vova7890 ★★★
() автор топика

Возможно ли как то удалить объект QTcpSocket не закрывая дескриптор? Чтобы в каждом треде по новому QTcpSocket + setSocketDescriptor и погнали наши городских?

man 7 tcp, открываешь сокет и вперед

annulen ★★★★★
()
Ответ на: комментарий от annulen

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

vova7890 ★★★
() автор топика

Так вот, а если мне надо, что бы этот сокет побывал по очереди в разных тредах

Это повод задуматься от архитектуре и о том что ты делаешь не так.

dhampire ★★★
()
Ответ на: комментарий от vova7890

главное открыть сокет, для остального есть setSocketDescriptor (или даже QSocketNotifier)

annulen ★★★★★
()
Ответ на: комментарий от dhampire

Ждал тебя. В начале поста я написал, что я принёс мега архитектуру и куте такой поганый не ложится в концепт? Это просто оценка возможности использования QtNetwork с разных ракурсов, в проекте.

vova7890 ★★★
() автор топика

Ты что-то не то хочешь, и кто только придумал разрешать переопределять класс QThread, эх... Ну рассылай-принимай данный от разных потоков в одном классе.

I-Love-Microsoft ★★★★★
()

Даже если бы так можно было, все равно были бы проблемы с возможной потерей данных из сокета. Насколько я понимаю qсокет вычитывает данные из системного сокета во внутренний буфер. Если ты в предыдущем треде удаляешь сокет в неудачный момент (до обработки readyRead), а в новом треде реюзаешь системный дескриптор в новом qсокете, то у тебя может выкусываться часть входящих данных. Актуально если данные могут прийти в случайный момент. Впрочем тогда не нужна подобная архитектура с чехардой тредов. Вообще ты не объяснил зачем такая архитектура. Даже если по командам клиента нужно запускать задачи в разных тредах, все равно логичнее парсить в одном.

anonymous
()
Ответ на: комментарий от I-Love-Microsoft

не переопределяю, просто, допустим, есть пул воркеров, изначально сокет порождается вне воркеров, а где-то «там»(от QTcpServer), чтобы выяснить, что с ним делать, если дальше с ним всё понятно, он отдаётся в какой-то из воркеров, дабы работа с сокетом (тобишь выгреб ивентов) и работа с протоколом была в одном воркере.

vova7890 ★★★
() автор топика
Ответ на: комментарий от anonymous

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

vova7890 ★★★
() автор топика
Ответ на: комментарий от vova7890

Это значит, что в Qt сокеты приколачиваются к треду

Зря ты лезешь в Qt, не понимая основ. Это QObject приколачивается к потоку, а точнее обработка его сигналов и слотов.

Так вот, а если мне надо, что бы этот сокет побывал по очереди в разных тредах, то как поступать в такой ситуации?

Как тебе уже правильно написали, не стоит лепить такой бордель. У тебя явные проблемы с архитектурой приложения.

MuZHiK-2 ★★★★
()
Ответ на: комментарий от Harald

можно создавать сокет в одном потоке, а читать-писать в других )

так это же не отменяет необходимость разделения доступа, типа мютексов

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

x905 ★★★★★
()

Не там и не так использовал moveToThread, решает в принципе.

vova7890 ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.