Как писать на нескольких QTcpSockets, используя QThreads?

Я уже пару дней борюсь с этой проблемой на QTcpSockets и QThreads.

У меня есть QTcpServer, который прослушивает порт и создает нового клиента, используя метод nextPendingConnection(). Итак, теперь у клиента есть qtcpsocket, который я могу использовать для чтения и записи.

Предположим, к моему серверу подключено 100 клиентов. Когда один из них хочет передать сообщение всем, мой основной поток (где я создаю клиентов с помощью nextPendingConnection() ) должен будет перебрать более 100 клиентов и вызвать метод записи для их сокетов. Если, например, 10 пользователей транслируют одновременно, мне придется сделать 1000 итераций, поэтому, на мой взгляд, на стороне клиента будет некоторая задержка (когда пользователь получает сообщения).

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

Я прочитал пример сервера фортуны, но он не решает мою проблему, потому что они уничтожают сокет после отправки данных; Я не хочу уничтожать свой сокет, потому что мне нужно прослушивать его для входящих сообщений (чтобы я мог их транслировать).

Одна вещь, о которой я подумал, это иметь 2 сокета для каждого клиента (на сервере и на стороне клиента); так что я оставляю один сокет для чтения, а другой я могу использовать, как в примере с сервером потоков удачи; в этом случае я бы также использовал пул потоков, чтобы ограничить количество задач (иначе это было бы то же самое, что использовать один поток для каждого клиента).

Не могли бы вы указать мне правильное направление или дать мне несколько советов о том, как реализовать запись параллельных сокетов без фактического наличия одного потока на клиенте...?

С уважением,

Себастьян


person Sebastian    schedule 05.11.2011    source источник


Ответы (1)


Иметь функцию WriteToSocket, которая записывает данные в определенный сокет. Кроме того, у вас должна быть очередь, содержащая данные, привязанные к сокету, защищенному мьютексом. В функции добавьте данные, которые вы хотите отправить, в очередь для сокета. Проверьте, назначен ли сокет уже потоку (сохраните для этой цели флаг). Если да, то все готово. Если нет, запланируйте задание для пула потоков, чтобы отправить данные из сокета.

В зависимости от множества деталей вы можете предпочесть альтернативную реализацию. В этой реализации логика отправки для каждого сокета имеет два режима: в очереди и вне очереди. Сокеты запускаются вне очереди. Когда вы хотите отправить в сокет, установите блокировку, которая его защищает. Если он находится в режиме очереди, добавьте данные в очередь, и все готово.

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

Вам нужно будет организовать некоторый механизм для «периодической» попытки отправки данных в сокеты в режиме очереди. Обычно вы делаете это с помощью чего-то вроде «выбрать» или «опрос». С QTcpSockets у вас есть сигналы и слоты.

person David Schwartz    schedule 05.11.2011
comment
Здравствуйте и спасибо за ваш ответ. Я думаю, что ваше решение очень хорошее, но я действительно не знаю, как его реализовать. Предположим, что мой tcpsocket (используемый только для чтения) испускает сигнал readyRead(); В отдельном потоке мне пришлось бы записывать данные для отправки всем пользователям в очереди каждого записывающего сокета, а затем другой поток фактически записывал данные из очереди в сокет. Возможно, я неправильно понял ваше объяснение... Я попытаюсь реализовать его и опубликую некоторые новости... Еще раз большое спасибо --Себ-- - person Sebastian; 05.11.2011