Выбор и реализация типа многопоточности, пул потоков, поток на соединение или один поток |
Здравствуйте, гость ( Вход | Регистрация )
Выбор и реализация типа многопоточности, пул потоков, поток на соединение или один поток |
mezmay |
27.11.2012, 23:53
Сообщение
#1
|
Активный участник Группа: Участник Сообщений: 272 Регистрация: 13.7.2009 Из: Ростов-на-Дону Пользователь №: 904 Спасибо сказали: 16 раз(а) Репутация: 1 |
Для саморазвития решил написать чат с базой данных, многопоточностью и голосовой связью. Клиенты будут подключаться к серверу и все сообщения посылать через него. Как реализовать многопоточность в данном случае? Хорошо понимаю 2 варианта:
1. Один дополнительный поток. Он все время запущен, принимает коннекты и передает/принимает данные от всех клиентов, пишет в базу. 2. Один поток на каждое соединение. Запущен пока есть коннект, обменивается данными с одним клиентом ну и пишет в общую базу. 3. Хотелось бы услышать советы, ведь оба предложенных варианта нехорошие - первый плох тем, что будет перегружен один поток, а второй плох тем, что количество потоков зависит от количества подключений и может быть неоптимальным. Изучал документацию по пулу потоков в Qt, но так и не понял как его прикрутить к данной задаче, ведь надо сделать чтобы рабочий объект существовал в потоке в течении, как минимум, одного коннекта. Или может сразу создать несколько потоков и клиентов распихивать по ним?... Сообщение отредактировал mezmay - 27.11.2012, 23:57 |
|
|
Алексей1153 |
28.11.2012, 6:29
Сообщение
#2
|
фрилансер Группа: Участник Сообщений: 2941 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: 34 |
можно попробовать так:
1) поток с GUI (основной) 2) поток сервера - слушает соединения, подключает 3)а) поток обслуживания клиентов - работает с массивом клиентов. Перебирает по очереди подключения, опрашивает, исполняет, отсылает 3)б) либо каждого клиента обрабатывать отдельным потоком (но это более морочно, и вряд ли понадобится) и не забывать про синхронизацию, конечно Сообщение отредактировал Алексей1153 - 28.11.2012, 6:30 |
|
|
mezmay |
29.11.2012, 13:30
Сообщение
#3
|
Активный участник Группа: Участник Сообщений: 272 Регистрация: 13.7.2009 Из: Ростов-на-Дону Пользователь №: 904 Спасибо сказали: 16 раз(а) Репутация: 1 |
Я все-таки хочу использовать количество рабочих потоков, равное QThread::idealThreadCount(),
и начал делать так: один поток принимает коннекты и запускает по мере необходимости рабочие потоки, в которые передает принятые сокеты. Таким образом получается, что у меня запущено, например, 8 рабочих потоков, и каждый обрабатывает по 4 клиента. Вот например от клиента А пришло сообщение для клиента В, но клиент А обрабатывается в одном потоке, а клиент В в другом, как в этом случае передать к В принятые от А данные? Сообщение отредактировал mezmay - 29.11.2012, 13:43 |
|
|
Алексей1153 |
29.11.2012, 14:22
Сообщение
#4
|
фрилансер Группа: Участник Сообщений: 2941 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: 34 |
усложнения с настройкой количества потоков - сомнительная выгода. Не советую Лучше тогда по одному потоку на клиента. И не париться.
Вот например от клиента А пришло сообщение для клиента В, но клиент А обрабатывается в одном потоке, а клиент В в другом, как в этом случае передать к В принятые от А данные? не понял вопроса. Если это соединённые клиенты с разных концов сокета, то один передаёт в сокет, другой принимает из сокета. Или что имеется в виду ? |
|
|
mezmay |
29.11.2012, 14:32
Сообщение
#5
|
Активный участник Группа: Участник Сообщений: 272 Регистрация: 13.7.2009 Из: Ростов-на-Дону Пользователь №: 904 Спасибо сказали: 16 раз(а) Репутация: 1 |
Ну допустим у нас по одному потоку на клиента - проблемы те же. Пользователь А шлет сообщение пользователю В. Оно приходит на сервер в поток threadA и в нем считывается. Пользователь В обрабатывается в потоке threadB (ну то есть соответствующий этому пользователю сокет QTcpSocket). Итак, сообщение от пользователя А принято в потоке threadA, а отправлено должно быть пользователю В. Как это сделать?
|
|
|
Алексей1153 |
29.11.2012, 14:36
Сообщение
#6
|
фрилансер Группа: Участник Сообщений: 2941 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: 34 |
в твоём классе-потоке сервера должен быть список подключенных им сокетов клиентов. Сокеты ты каким-то образом маркируешь - вот по этой метке и найдёшь, кому передать данные
|
|
|
mezmay |
29.11.2012, 14:48
Сообщение
#7
|
Активный участник Группа: Участник Сообщений: 272 Регистрация: 13.7.2009 Из: Ростов-на-Дону Пользователь №: 904 Спасибо сказали: 16 раз(а) Репутация: 1 |
Да, сокеты хранить и найти нужный не проблема. Но как синхронизировать? Нельзя же писать в один сокет socketB из двух потоков одновременно
|
|
|
Iron Bug |
29.11.2012, 18:10
Сообщение
#8
|
Профессионал Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: 12 |
по-моему, тебе лучше разделить потоки на приём и отправку. тогда у тебя будут уникальные точки входа. ну а более простую синхронизацию - стандартными средствами. наверняка в Qt поддерживаются мьютексы и прочие средства синхронизации потоков.
|
|
|
Алексей1153 |
30.11.2012, 11:11
Сообщение
#9
|
фрилансер Группа: Участник Сообщений: 2941 Регистрация: 19.6.2010 Из: Обливион Пользователь №: 1822 Спасибо сказали: 215 раз(а) Репутация: 34 |
|
|
|
mezmay |
30.11.2012, 15:26
Сообщение
#10
|
Активный участник Группа: Участник Сообщений: 272 Регистрация: 13.7.2009 Из: Ростов-на-Дону Пользователь №: 904 Спасибо сказали: 16 раз(а) Репутация: 1 |
Из документации QAbstractSocket:
Цитата Note: It is not possible to initialize two abstract sockets with the same native socket descriptor. Ну а использовать один нельзя, т.к. он не thread-safe |
|
|
Текстовая версия | Сейчас: 29.11.2024, 21:53 |