Для саморазвития решил написать чат с базой данных, многопоточностью и голосовой связью. Клиенты будут подключаться к серверу и все сообщения посылать через него. Как реализовать многопоточность в данном случае? Хорошо понимаю 2 варианта:
1. Один дополнительный поток. Он все время запущен, принимает коннекты и передает/принимает данные от всех клиентов, пишет в базу.
2. Один поток на каждое соединение. Запущен пока есть коннект, обменивается данными с одним клиентом ну и пишет в общую базу.
3. Хотелось бы услышать советы, ведь оба предложенных варианта нехорошие - первый плох тем, что будет перегружен один поток, а второй плох тем, что количество потоков зависит от количества подключений и может быть неоптимальным. Изучал документацию по пулу потоков в Qt, но так и не понял как его прикрутить к данной задаче, ведь надо сделать чтобы рабочий объект существовал в потоке в течении, как минимум, одного коннекта. Или может сразу создать несколько потоков и клиентов распихивать по ним?...
Алексей1153
28.11.2012, 6:29
можно попробовать так:
1) поток с GUI (основной)
2) поток сервера - слушает соединения, подключает
3)а) поток обслуживания клиентов - работает с массивом клиентов. Перебирает по очереди подключения, опрашивает, исполняет, отсылает
3)б) либо каждого клиента обрабатывать отдельным потоком (но это более морочно, и вряд ли понадобится)
и не забывать про синхронизацию, конечно
Я все-таки хочу использовать количество рабочих потоков, равное QThread::idealThreadCount(),
и начал делать так: один поток принимает коннекты и запускает по мере необходимости рабочие потоки, в которые передает принятые сокеты. Таким образом получается, что у меня запущено, например, 8 рабочих потоков, и каждый обрабатывает по 4 клиента. Вот например от клиента А пришло сообщение для клиента В, но клиент А обрабатывается в одном потоке, а клиент В в другом, как в этом случае передать к В принятые от А данные?
Алексей1153
29.11.2012, 14:22
усложнения с настройкой количества потоков - сомнительная выгода. Не советую
Лучше тогда по одному потоку на клиента. И не париться.
Цитата(mezmay @ 29.11.2012, 16:30)
Вот например от клиента А пришло сообщение для клиента В, но клиент А обрабатывается в одном потоке, а клиент В в другом, как в этом случае передать к В принятые от А данные?
не понял вопроса. Если это соединённые клиенты с разных концов сокета, то один передаёт в сокет, другой принимает из сокета.
Или что имеется в виду ?
Ну допустим у нас по одному потоку на клиента - проблемы те же. Пользователь А шлет сообщение пользователю В. Оно приходит на сервер в поток threadA и в нем считывается. Пользователь В обрабатывается в потоке threadB (ну то есть соответствующий этому пользователю сокет QTcpSocket). Итак, сообщение от пользователя А принято в потоке threadA, а отправлено должно быть пользователю В. Как это сделать?
Алексей1153
29.11.2012, 14:36
в твоём классе-потоке сервера должен быть список подключенных им сокетов клиентов. Сокеты ты каким-то образом маркируешь - вот по этой метке и найдёшь, кому передать данные
Да, сокеты хранить и найти нужный не проблема. Но как синхронизировать? Нельзя же писать в один сокет socketB из двух потоков одновременно
Iron Bug
29.11.2012, 18:10
по-моему, тебе лучше разделить потоки на приём и отправку. тогда у тебя будут уникальные точки входа. ну а более простую синхронизацию - стандартными средствами. наверняка в Qt поддерживаются мьютексы и прочие средства синхронизации потоков.
Алексей1153
30.11.2012, 11:11
Цитата(mezmay @ 29.11.2012, 17:48)
Нельзя же писать в один сокет socketB из двух потоков одновременно
это в доках сказано ?
Из документации QAbstractSocket:
Цитата
Note: It is not possible to initialize two abstract sockets with the same native socket descriptor.
Ну а использовать один нельзя, т.к. он не thread-safe
Алексей1153
30.11.2012, 19:56
это сказано о том, что один экземпляр - один сокет.
Я не понимаю, что тебя беспокоит то.
Смотри:
1) принимаешь данные из сокета A
2) передаёшь эти данные в любой поток - хоть в тот же самый (вот тут синхронизация и нужна)
3) заливаешь данные в сокет B
где я что упустил ?
Litkevich Yuriy
30.11.2012, 20:17
Цитата(Алексей1153 @ 30.11.2012, 21:56)
1) принимаешь данные из сокета A
2) передаёшь эти данные в любой поток - хоть в тот же самый (вот тут синхронизация и нужна)
3) заливаешь данные в сокет B
где я что упустил ?
ну т.е. есть некий посредник между потоками и сокетом, ты это имеешь в виду?
Алексей1153
30.11.2012, 20:22
ну, к примеру, это std::vector<uint8_t> или QByteArray
и даже не посредник, а "данные-ответ"
подвоха всё равно не вижу
Чат дорос до бета-версии, установил на работе, вот что получилось:
Iron Bug
18.12.2012, 19:04
Цитата(mezmay @ 18.12.2012, 18:46)
Чат дорос до бета-версии, установил на работе, вот что получилось:
ща тебя уволят: потому что работники вместо работы будут торчать в чате
Начальник - свой человек, тоже в чате))
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.