Рассмотрим, как создать многопоточное клиент-серверное приложение. Фактически оно будет отличаться от однопоточного только тем, что обработка запроса клиента будет вынесена в отдельный поток.
Вначале создадим проект для клиента. Назовем проект ConsoleClient и в классе Program определим следующий код:
В программе клиента пользователь будет вначале вводить свое имя, а затем сообщение для отправки. Причем сообщение будет уходить в формате Имя: сообщение .
После отправки сообщения клиент получает сообщение с сервера.
Теперь создадим проект сервера, который назовем ConsoleServer. Вначале в проект сервера добавим новый класс ClientObject , который будет представлять отдельное подключение:
В этом классе, наоборот, сначала получаем сообщение в цикле do..while и потом немного его изменяем (отрезаем по двоеточию и переводим в верхний регистр) и отправляем обратно клиенту. То есть класс ClientObject заключает в себе все действия по работе с отдельным подключением.
В главном классе проекта сервера определим следующий код:
Сразу после подключения нового клиента:
Создается объект ClientObject и новый поток, который запускает метод Process объекта ClientObject, где собственно и происходит получение и отправка сообщений. Таким образом, сервер сможет одновременно обрабатывать сразу несколько запросов.
Результаты работы программы. Один из клиентов:
4 Eddie [2011-02-23 00:23:00]
Мой TCP-сервер прослушивает порт 5003. Когда соединение выполняется, я хочу создать поток и запустить функцию interpMessage. У меня есть несколько вопросов об этом.
1) Я делаю вызов malloc и бесплатно в правильных местах?
2) После вызова pthread_create мой код сразу переходит к «free (child)»; а затем вернуться к началу цикла while?
3) Что произойдет, если 5 человек подключится в одно и то же время (как работает код для создания 5 потоков?)
c multithreading tcp client
1 ответ
Ваш код правильно использует malloc и free , но способ, которым вы это делаете, делает реализацию более сложной, чем это необходимо. Функция pthread_create работает, записывая идентификатор нового потока в память, на которую указывает первый параметр. В вашем случае вы динамически выделили этот буфер, а затем немедленно освободили его. Следовательно, память привязана к одной итерации цикла while . Если это то, что вы хотите, вам, вероятно, лучше просто сделать выделенное стек pthread_t и передать указатель на него в pthread_create :
Теперь, когда child локально привязан к циклу, управление памятью будет обрабатываться автоматически без необходимости вызова malloc или free .
Что касается второго вопроса о том, продолжает ли элемент управления free (child) , а затем возвращается в верхнюю часть цикла после вызова pthread_create , да, это правильно. Будет создан второй поток, выполняющий interpretMessage , поэтому может произойти некоторая задержка, если исходный процесс задерживается, но контроль возобновляется с этой точки.
Для вашего последнего вопроса, если пять человек все подключаются точно в одно и то же время, то в следующие пять раз вы вызываете accept , функция будет предоставлять один сокет для следующего входящего соединения. То есть ОС будет автоматически помещать входящие соединения в некоторый порядок, и на каждой итерации цикла ваш код заметит, что там есть соединение, получить сокет для него, а затем отлить поток для обработки сообщения.
Одна вещь, которую я заметил в вашем коде — когда вы создаете поток для вызова interpretMessage , вы не указали никаких аргументов функции, и поэтому каждый поток будет работать без какого-либо контекста для того, как он был создан, Было ли это намеренно?
Нужно написать сервер для приёма данных от разных по типу устройств с подтверждением приёма. Устройства присылают разные данные и алгоритм общения с каждым типом устройств разный. Из-за скудного знания с++ столкнулся с проблемой реализации. Я хочу пойти по следующему пути: запускаю служащий сервер. При приеме данных (первый пакет устройства — идентификатор типа устройства и его номер) созданный сокет отправляется в отдельный поток и дальше идёт обработка данных определённого устройства в отдельном потоке. Проблема: у меня есть класс с алгоритмом обработки пакетов идентификаторов и создание общего сокета. После создания экземпляра и приёма нужного пакета идентификатора не знаю как передать данный сокет в новый поток с новым алгоритмом обработки пакетов. Делаю это я для того, чтобы уменьшить длину передаваемых данных и снизить нагрузку на процессор (избавлюсь от множества условных операторов при каждом принятом пакете). Возможно у меня неправильная логика, поэтому прошу направить на правильный алгоритм. Моя реализация многопоточности: создаю экземпляр Qthread и с помощью MoveToThread передаю экземпляр с сокетом и обработки данных устройства. С потоками я ещё не до конца разобрался. Насколько я понял, в qt можно создать поток и поместить в него объект и только ловить сигналы от потока.