Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.54/26: Рейтинг темы: голосов - 26, средняя оценка - 4.54
28 / 29 / 5
Регистрация: 17.10.2009
Сообщений: 739

Многопоточный чат с использованием пула потоков

23.03.2014, 19:10. Показов 5746. Ответов 55
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
есть вопрос как реализовать можно чат с использованием пулов потоков.Без пула все понятно на каждого клиента создается поток и потоки висят и делают свои дела,в пуле я читал создается n-ое количество потоков и они обрабатывают свои задачи,тоесть если у меня 4 потока в пуле то только 4 пользователя смогут работать и все,а остальные будут в очереди или я не правильно что то понимаю

Добавлено через 43 минуты
неужели никто не использовал пул потоков?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
23.03.2014, 19:10
Ответы с готовыми решениями:

Вызов конструктора и деструктора с использованием пула
У меня есть некоторая область памяти (указатель на её начало и размер в байтах), часть которой необходимо превратить в объект. У объекта...

Помощь с использованием потоков
Добрый вечер, вот пишу программу, которая создает 2 потока, первый считает в файле кол-во символов и записывает в файл, второй считает...

Обработка матриц с использованием файлов и потоков
Задание такое: Создать класс matrica с заранее неизвестным количеством элементов. Предусмотреть члены-функции: 1) Введение с файла...

55
Каратель
Эксперт С++
6610 / 4029 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
23.03.2014, 19:21
Цитата Сообщение от sergeu90 Посмотреть сообщение
есть вопрос как реализовать можно чат с использованием пулов потоков
так в чем вопрос? появился клиент - достали из пула поток и отдали его клиенту, если свободного потока нету, поставили клиента в очередь
1
28 / 29 / 5
Регистрация: 17.10.2009
Сообщений: 739
23.03.2014, 19:40  [ТС]
Jupiter,вопрос возник в том что получается у меня в системе будет только определенное количество пользователей допустим в пуле 10 потоков значит одновременно может быть только 10 клиентов,остальные клиенты подсоеденяются и ждут когда пул потоков обработает их задачу я правильно понял?

Добавлено через 7 минут
Jupiter, получается что по сути лучше использовать на каждого клиента свой поток ?бесконечное количество пользователей будет,а с пулом получается нет?
0
Каратель
Эксперт С++
6610 / 4029 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
23.03.2014, 19:55
Цитата Сообщение от sergeu90 Посмотреть сообщение
бесконечное количество пользователей будет,а с пулом получается нет?
в ОС есть ограничение на количество потоков на процесс

Цитата Сообщение от sergeu90 Посмотреть сообщение
получается что по сути лучше использовать на каждого клиента свой поток ?
лучше или хуже зависит от количества пользователей, продолжительности задачи каждого пользователя и т.д. и т.п.
1
28 / 29 / 5
Регистрация: 17.10.2009
Сообщений: 739
24.03.2014, 17:17  [ТС]
Jupiter, просто у меня стоит задача курсового пул потоков,я решил на курсовую сделать чат с использованием пула,может подскажите какую-нибудь идею для курсового с использованием пула потоков?

Добавлено через 21 час 6 минут
никто не подскажет?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
24.03.2014, 21:47
Цитата Сообщение от sergeu90 Посмотреть сообщение
тоесть если у меня 4 потока в пуле то только 4 пользователя смогут работать и все,а остальные будут в очереди или я не правильно что то понимаю
Неправильно понимаете.
Сетевой ввод-вывод по своей природе устроен так, что там
постоянно происходит ожидание выполнения каких-то операций -
пинг, handshake, connect/disconnect, send, receive и т.д.

Пока сетевое оборудование занимается обработкой операции,
поток разгружается и может взять на себя еще что-нибудь.
Например, обработать результат операции, которая только
что завершилась. После чего поток снова "возвращается" в пул.

То есть, небольшое количество потоков легко могут обслуживать
десятки и сотни клиентов, а иногда на порядки больше.
1
28 / 29 / 5
Регистрация: 17.10.2009
Сообщений: 739
24.03.2014, 22:34  [ТС]
Убежденный, ну это я понимаю что операция завершилась поток освободился можно взять другую задачу,а если у меня допустим 4 потока будут висеть все время и в бесконечном цикле крутиться пока клиент не дисконект то получится что очередь все таки будет
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
24.03.2014, 23:05
Хм. А что именно будут делать эти потоки в бесконечном цикле ?
И главное - зачем ?
1
28 / 29 / 5
Регистрация: 17.10.2009
Сообщений: 739
25.03.2014, 01:18  [ТС]
Убежденный, они будут ждать от клиента действий и опять зысыпать,а как чат сделать тогда иначе?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
25.03.2014, 09:25
sergeu90, очень советую - найдите книгу "Программирование в
сетях Windows", почитайте в ней главу про модели сокетного ввода-вывода,
особенно что касается портов завершения (IOCP). Там вовсю
используются пулы потоков и характерные "примочки", которые с
ними связаны. Многие такие вопросы сами собой отпадут.
2
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
25.03.2014, 10:32
Цитата Сообщение от sergeu90 Посмотреть сообщение
они будут ждать от клиента действий и опять зысыпать,а как чат сделать тогда иначе?
использовать асинхронный ввод вывод, а не в цикле ждать когда удаленная сторона что то сделает,
на сокете появилась активность на чтение - читаем
писать как правило можно всегда, во время дисконнекта по моим наблюдениям появляется активность на чтение, но recv вернет 0 (0 может вернуть и в других ситуациях, важно при получении 0 байт проверить значение errno/WSAGetLastError())
0
28 / 29 / 5
Регистрация: 17.10.2009
Сообщений: 739
25.03.2014, 13:34  [ТС]
aLarman, ну я трошки не понимаю,как сделать асинхронный ввод вывод,я так и собирался делать в цикле бесконечном ждать активности от клиента,а как вот сделать иначе сложно)

Добавлено через 1 минуту
Убежденный, спасибо буду пробывать читать хотя до сих не понимаю как реализовать логику чата,что бы каждый поток не висел в бесконечном цикле
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
25.03.2014, 13:41
Цитата Сообщение от sergeu90 Посмотреть сообщение
а как вот сделать иначе сложно
почитайте про ф-ции select и poll (linux), и есть аналог select'a в винде (называется вроде так же)
в 2х словах, в эти ф-ции передаются дескрипторы (cокеты в вашем случае) и эти дескрипторы проверяются на активность (на чтение на запись на ошибки), и этот метод возвращает управление если есть хотя бы 1 активность, или после таймайта
на запись практически всегда будет активность (потому что писать можно практически всегда - забить буфер сложно, а ошибочные ситуации рассматривать не будем) поэтому достаточно проверять активность на чтение
соответственно как появилась активность на чтение даем задачу пулу обработать эту активность (вычитать данные), в данном случае если есть активность, то вызов recv не будет блокирующим
после чего делаем какие то действия с полученными данными, каким то образом реагируем на эти данные (возможно вызов какой то ф-ции) и поток завершает работу (точнее начинает ждать новой задачи)
что получается - есть что читать - читаем, нет ничего - простой, а опрашивать в цикле данные не стоит
0
28 / 29 / 5
Регистрация: 17.10.2009
Сообщений: 739
25.03.2014, 13:44  [ТС]
aLarman, и как тогда со стороны клиента держать соеденение что бы не отсоеденяться от сервера,так я делал что бы в потоке на сервере бесконечно крутился цикл и тогда клиент у меня не терялся тоесть не дисконектился

Добавлено через 1 минуту
aLarman, а можно пример кода примитивный самый простой что бы понять как это выглядит так сложно разобраться,ели не сложно не большой пример
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
25.03.2014, 13:45
Цитата Сообщение от sergeu90 Посмотреть сообщение
и как тогда со стороны клиента держать соеденение что бы не отсоеденяться от сервера
что Вы планируете использовать? UDP или TCP
0
28 / 29 / 5
Регистрация: 17.10.2009
Сообщений: 739
25.03.2014, 13:48  [ТС]
aLarman, планирую использовать TCP и хочу вот сделать что-нибудь на курсовой вроде как чата,но вот через пул потоков,для начала мне бы понять как вы сказали активность смотреть и в пул передавать

Добавлено через 1 минуту
aLarman, тоесть в пул я знаю как передавать,я собираюсь использовать winapi функции для работы с пулом
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
25.03.2014, 13:50
вот пример с 1 потоком на accept подключений, и множеством потоков на каждое сообщение (по сути можно на каждое сообщение не поток создавать, а отдавать ф-цию которая производит чтение в пул)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
class ClassMaster
{
    typedef std::set<SOCKET> ClientList_t;
    typedef std::map<SOCKET, boost::thread*> HandlerProcessThread_t;
public:
    void Dispatch(bool &bWork)
    {
        
        while(bWork)
        {
            //std::cout<<"dispatch" <<std::endl;
            if(!_Clients.empty())
            {
                //std::cout<<"Clients not empty" << std::endl;
                fd_set ReadSet;
                fd_set WriteSet;
                fd_set ExceptSet;
                FD_ZERO(&ReadSet);
                FD_ZERO(&WriteSet);
                FD_ZERO(&ExceptSet);
                ClientList_t::iterator Iter = _Clients.begin();
                for(int i = 0; Iter != _Clients.end() && i < FD_SETSIZE; ++Iter, ++i)
                {
                    ReadSet.fd_array[i] = *Iter;
                }
                ReadSet.fd_count = _Clients.size();
                memcpy(&ExceptSet, &ReadSet, sizeof(fd_set));
                ClientList_t::iterator MaxFdIter = --_Clients.end();
                timeval tm;
                tm.tv_usec = 10;
                tm.tv_sec = 0;
                int Fds = select(*MaxFdIter + 1, &ReadSet, &WriteSet, &ExceptSet, &tm);
                if(Fds == -1)
                {
                    std::cout<<"Select error: " << h_errno << std::endl;
                }
                //std::cout<<"Fds = " << Fds << std::endl;
                for(unsigned int i = 0; i < ReadSet.fd_count; i++)
                {
                    SOCKET sock = ReadSet.fd_array[i];
                    //std::cout<<"Read ready socket" << sock << std::endl;
                    ProcessRead(sock);
                }
                while(!_ClosedSocket.empty())
                {
                    Disconnect(_ClosedSocket.front());
                    _ClosedSocket.erase(_ClosedSocket.begin());
                }
 
            }
            //boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
        }
        
    }
    void AddClient(const SOCKET & sock)
    {
        _Clients.insert(sock);
        boost::thread * New = new boost::thread(&ClassMaster::ProcessWrite, boost::ref(*this), sock);
        _Threads.insert(std::make_pair(sock, New));
        //std::
    }
    void DeleteClient(const SOCKET & sock)
    {
        ClientList_t::iterator Iter = _Clients.begin();
        for(; Iter != _Clients.end(); ++Iter)
        {
            if(*Iter == sock)
            {
                _Clients.erase(Iter);
                break;
            }
        }
        if(_Threads.find(sock) != _Threads.end())
        {
            if(_Threads[sock]->joinable())
            {
                _Threads[sock]->detach();
            }
 
            delete _Threads[sock];
            _Threads.erase(sock);
        }
    }
    void ProcessRead(SOCKET sock)
    {
        char msg[1024];
        int n = 0;
        n = recv(sock, msg, 1024,0);
        
 
        int SockError = 0;
        int Len = sizeof(SockError);
        if(n <= 0)
        {
            Disconnect(sock);
        }
        else
        {
            std::cout<< "Remote said: ";
            for(int i = 0; i < n; i ++)
            {
                std::cout<< msg[i]<<"";
            }
            std::cout << std::endl;
        }
    }
    void ProcessWrite(SOCKET sock)
    {
        char msg[1024];
        std::string mes;
        while(1)
        {
            getline(std::cin,mes);
            if(mes == "q")
            {
                break;
            }
            int n = 0;
            n = send(sock, mes.c_str(), mes.length(),0);
        }
        _ClosedSocket.push_back(sock);
    }
    void Disconnect(const SOCKET &sock)
    {
        DeleteClient(sock);
        closesocket(sock);
        std::cout << "Client has disconnected." << std::endl;
    }
private:
    ClientList_t _Clients;
    HandlerProcessThread_t _Threads;
    std::list<SOCKET> _ClosedSocket;
};
 
SOCKET CreateServerSocket(SOCKET & ServerSocket)
{
    ServerSocket = socket(AF_INET, SOCK_STREAM, 0);
    if(ServerSocket == INVALID_SOCKET)
    {
        std::cout << "Error of creating socket: code " << h_errno << std::endl;
        return false;
    }
    sockaddr_in ServerAddress;
    memset(&ServerAddress,0,sizeof(ServerAddress));
    ServerAddress.sin_family = AF_INET;
    //ServerAddress.sin_addr.s_addr=INADDR_ANY;
    /*ServerAddress.sin_addr.S_un.S_un_b.s_b1 = 192;
    ServerAddress.sin_addr.S_un.S_un_b.s_b2 = 168;
    ServerAddress.sin_addr.S_un.S_un_b.s_b3 = 133;
    ServerAddress.sin_addr.S_un.S_un_b.s_b4 = 85;*/
    ServerAddress.sin_addr.s_addr = inet_addr("192.168.133.85");
    ServerAddress.sin_port=htons(17000);
    if(bind(ServerSocket, (sockaddr *)&ServerAddress,sizeof(ServerAddress)))
    {
        std::cout << "Error of binding socket: code " << h_errno << std::endl;
        return false;
    }
    if(listen(ServerSocket, 10))
    {
        std::cout << "Error of going listened socket: code " << h_errno << std::endl;
        return false;
    }
    return true;
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    WSAData WsaData;
    WSAStartup(MAKEWORD(2,0),&WsaData);
    SOCKET ServerSocket = 0;
    if(!CreateServerSocket(ServerSocket))
    {
        system("pause");
        return 0;
    }
    sockaddr_in ClientAddress;
    int ClientAddressSize = sizeof(ClientAddress);
    memset(&ClientAddress,0,sizeof(ClientAddress));
    SOCKET ClientSocket;
    ClassMaster Master;
    bool bWork = true;
    boost::thread ThreadDispatcher(&ClassMaster::Dispatch, boost::ref(Master), boost::ref(bWork));
    while(1)
    {
        ClientSocket = accept(ServerSocket, (sockaddr*)&ClientAddress, &ClientAddressSize);
        if(ClientSocket == INVALID_SOCKET)
        {
            std::cout << "Error of accept socket: code " << h_errno << std::endl;
        }
        std::cout<<"Has connection!"<<std::endl;
        std::cout<<"Client: " << (int)ClientAddress.sin_addr.S_un.S_un_b.s_b1 <<"." << 
            (int)ClientAddress.sin_addr.S_un.S_un_b.s_b2 << "." << (int)ClientAddress.sin_addr.S_un.S_un_b.s_b3 << "." <<
            (int)ClientAddress.sin_addr.S_un.S_un_b.s_b4 << ":" << ClientAddress.sin_port <<std::endl;
        Master.AddClient(ClientSocket);
    }
    /*boost::thread tr(Func);
    boost::this_thread::sleep_for(boost::chrono::milliseconds(3000));
    tr.interrupt();
    */
    bWork = false;
    ThreadDispatcher.join();
    system("pause");
    return 0;
}
Добавлено через 1 минуту
ф-ция Dispatch() в цикле Вызывает select + доп. действия

Добавлено через 49 секунд
Цитата Сообщение от aLarman Посмотреть сообщение
и множеством потоков на каждое сообщение
усп ошибся, тут поток на 1 клиента
1
28 / 29 / 5
Регистрация: 17.10.2009
Сообщений: 739
25.03.2014, 13:53  [ТС]
aLarman, получается это не пул тут я так понял ?
0
654 / 575 / 164
Регистрация: 13.12.2012
Сообщений: 2,124
25.03.2014, 13:58
да, в методе Dispatch там где вызывается
C++
1
ProcessRead(sock);
заменить на добавление задачи в пул, и соответственно в AddClient не создавать потоки для каждого клиента (эти потоки используются для получение ввода, и отправки сообщений клиенту - реализация не самая ровная потому что там есть блокирующий вызов - вызов cin)
1
28 / 29 / 5
Регистрация: 17.10.2009
Сообщений: 739
25.03.2014, 14:00  [ТС]
aLarman, спасибо начну разбираться на днях)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
25.03.2014, 14:00
Помогаю со студенческими работами здесь

Максимальный элемент матрицы с использованием потоков
#include &quot;stdafx.h&quot; #include &lt;Windows.h&gt; #include &lt;iostream&gt; #include &lt;conio.h&gt; using namespace std; int *Mas; struct...

Поиск в бинарном файле с использованием файловых потоков
Подскажите как реализовать поиск объекта в бинарном файле.(телефонный справочник, поиск по названию абонента)

Сервер с использованием пула потоков для параллельной обработки запросов клиентов
Разработать сервер с использованием пула потоков для параллельной обработки запросов клиентов. К серверу подключается много клиентов, все...

Синхронизация пула потоков
Всем привет! Задаю я, наверное, такой вопрос не первый и уж явно не последний. Тема такая: using (ManualResetEvent mre = new...

Ожидание завершения пула потоков
Нужно чтоб результат этого кода возвращался по завершению выполнения всех потоков в пуле ExecutorService exService =...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru