Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Выбор и реализация типа многопоточности
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Общие вопросы
mezmay
Для саморазвития решил написать чат с базой данных, многопоточностью и голосовой связью. Клиенты будут подключаться к серверу и все сообщения посылать через него. Как реализовать многопоточность в данном случае? Хорошо понимаю 2 варианта:

1. Один дополнительный поток. Он все время запущен, принимает коннекты и передает/принимает данные от всех клиентов, пишет в базу.
2. Один поток на каждое соединение. Запущен пока есть коннект, обменивается данными с одним клиентом ну и пишет в общую базу.
3. Хотелось бы услышать советы, ведь оба предложенных варианта нехорошие - первый плох тем, что будет перегружен один поток, а второй плох тем, что количество потоков зависит от количества подключений и может быть неоптимальным. Изучал документацию по пулу потоков в Qt, но так и не понял как его прикрутить к данной задаче, ведь надо сделать чтобы рабочий объект существовал в потоке в течении, как минимум, одного коннекта. Или может сразу создать несколько потоков и клиентов распихивать по ним?...
Алексей1153
можно попробовать так:

1) поток с GUI (основной)

2) поток сервера - слушает соединения, подключает

3)а) поток обслуживания клиентов - работает с массивом клиентов. Перебирает по очереди подключения, опрашивает, исполняет, отсылает
3)б) либо каждого клиента обрабатывать отдельным потоком (но это более морочно, и вряд ли понадобится)


и не забывать про синхронизацию, конечно
mezmay
Я все-таки хочу использовать количество рабочих потоков, равное QThread::idealThreadCount(),
и начал делать так: один поток принимает коннекты и запускает по мере необходимости рабочие потоки, в которые передает принятые сокеты. Таким образом получается, что у меня запущено, например, 8 рабочих потоков, и каждый обрабатывает по 4 клиента. Вот например от клиента А пришло сообщение для клиента В, но клиент А обрабатывается в одном потоке, а клиент В в другом, как в этом случае передать к В принятые от А данные?
Алексей1153
усложнения с настройкой количества потоков - сомнительная выгода. Не советую :) Лучше тогда по одному потоку на клиента. И не париться.

Цитата(mezmay @ 29.11.2012, 16:30) *
Вот например от клиента А пришло сообщение для клиента В, но клиент А обрабатывается в одном потоке, а клиент В в другом, как в этом случае передать к В принятые от А данные?

не понял вопроса. Если это соединённые клиенты с разных концов сокета, то один передаёт в сокет, другой принимает из сокета.
Или что имеется в виду ?
mezmay
Ну допустим у нас по одному потоку на клиента - проблемы те же. Пользователь А шлет сообщение пользователю В. Оно приходит на сервер в поток threadA и в нем считывается. Пользователь В обрабатывается в потоке threadB (ну то есть соответствующий этому пользователю сокет QTcpSocket). Итак, сообщение от пользователя А принято в потоке threadA, а отправлено должно быть пользователю В. Как это сделать?
Алексей1153
в твоём классе-потоке сервера должен быть список подключенных им сокетов клиентов. Сокеты ты каким-то образом маркируешь - вот по этой метке и найдёшь, кому передать данные
mezmay
Да, сокеты хранить и найти нужный не проблема. Но как синхронизировать? Нельзя же писать в один сокет socketB из двух потоков одновременно
Iron Bug
по-моему, тебе лучше разделить потоки на приём и отправку. тогда у тебя будут уникальные точки входа. ну а более простую синхронизацию - стандартными средствами. наверняка в Qt поддерживаются мьютексы и прочие средства синхронизации потоков.
Алексей1153
Цитата(mezmay @ 29.11.2012, 17:48) *
Нельзя же писать в один сокет socketB из двух потоков одновременно

это в доках сказано ?
mezmay
Из документации QAbstractSocket:
Цитата
Note: It is not possible to initialize two abstract sockets with the same native socket descriptor.

Ну а использовать один нельзя, т.к. он не thread-safe
Алексей1153
это сказано о том, что один экземпляр - один сокет.

Я не понимаю, что тебя беспокоит то.

Смотри:

1) принимаешь данные из сокета A
2) передаёшь эти данные в любой поток - хоть в тот же самый (вот тут синхронизация и нужна)
3) заливаешь данные в сокет B

где я что упустил ?
Litkevich Yuriy
Цитата(Алексей1153 @ 30.11.2012, 21:56) *
1) принимаешь данные из сокета A
2) передаёшь эти данные в любой поток - хоть в тот же самый (вот тут синхронизация и нужна)
3) заливаешь данные в сокет B
где я что упустил ?
ну т.е. есть некий посредник между потоками и сокетом, ты это имеешь в виду?
Алексей1153
ну, к примеру, это std::vector<uint8_t> или QByteArray

и даже не посредник, а "данные-ответ"

подвоха всё равно не вижу
mezmay
Чат дорос до бета-версии, установил на работе, вот что получилось:
Iron Bug
Цитата(mezmay @ 18.12.2012, 18:46) *
Чат дорос до бета-версии, установил на работе, вот что получилось:

ща тебя уволят: потому что работники вместо работы будут торчать в чате :D
mezmay
Начальник - свой человек, тоже в чате))
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.