Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
 
sergeu90
27 / 28 / 3
Регистрация: 17.10.2009
Сообщений: 739
23.03.2014, 19:10     Многопоточный чат с использованием пула потоков #1
есть вопрос как реализовать можно чат с использованием пулов потоков.Без пула все понятно на каждого клиента создается поток и потоки висят и делают свои дела,в пуле я читал создается n-ое количество потоков и они обрабатывают свои задачи,тоесть если у меня 4 потока в пуле то только 4 пользователя смогут работать и все,а остальные будут в очереди или я не правильно что то понимаю

Добавлено через 43 минуты
неужели никто не использовал пул потоков?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.03.2014, 19:10     Многопоточный чат с использованием пула потоков
Посмотрите здесь:

Максимальный элемент матрицы с использованием потоков C++
C++ Выполнить задания с использованием инструкции выбора if и с использованием условного оператора
Помощь с использованием потоков C++
Множественное наследование с использованием абстрактных базовых классов, файлового ввода-вывода с применением потоков С++, функций обработки исключи C++
C++ Создание и завершение процессов и потоков. Приоритеты выполнения потоков
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
23.03.2014, 19:21     Многопоточный чат с использованием пула потоков #2
Цитата Сообщение от sergeu90 Посмотреть сообщение
есть вопрос как реализовать можно чат с использованием пулов потоков
так в чем вопрос? появился клиент - достали из пула поток и отдали его клиенту, если свободного потока нету, поставили клиента в очередь
sergeu90
27 / 28 / 3
Регистрация: 17.10.2009
Сообщений: 739
23.03.2014, 19:40  [ТС]     Многопоточный чат с использованием пула потоков #3
Jupiter,вопрос возник в том что получается у меня в системе будет только определенное количество пользователей допустим в пуле 10 потоков значит одновременно может быть только 10 клиентов,остальные клиенты подсоеденяются и ждут когда пул потоков обработает их задачу я правильно понял?

Добавлено через 7 минут
Jupiter, получается что по сути лучше использовать на каждого клиента свой поток ?бесконечное количество пользователей будет,а с пулом получается нет?
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
23.03.2014, 19:55     Многопоточный чат с использованием пула потоков #4
Цитата Сообщение от sergeu90 Посмотреть сообщение
бесконечное количество пользователей будет,а с пулом получается нет?
в ОС есть ограничение на количество потоков на процесс

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

Добавлено через 21 час 6 минут
никто не подскажет?
Убежденный
Системный программист
 Аватар для Убежденный
14170 / 6185 / 981
Регистрация: 02.05.2013
Сообщений: 10,294
Завершенные тесты: 1
24.03.2014, 21:47     Многопоточный чат с использованием пула потоков #6
Цитата Сообщение от sergeu90 Посмотреть сообщение
тоесть если у меня 4 потока в пуле то только 4 пользователя смогут работать и все,а остальные будут в очереди или я не правильно что то понимаю
Неправильно понимаете.
Сетевой ввод-вывод по своей природе устроен так, что там
постоянно происходит ожидание выполнения каких-то операций -
пинг, handshake, connect/disconnect, send, receive и т.д.

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

То есть, небольшое количество потоков легко могут обслуживать
десятки и сотни клиентов, а иногда на порядки больше.
sergeu90
27 / 28 / 3
Регистрация: 17.10.2009
Сообщений: 739
24.03.2014, 22:34  [ТС]     Многопоточный чат с использованием пула потоков #7
Убежденный, ну это я понимаю что операция завершилась поток освободился можно взять другую задачу,а если у меня допустим 4 потока будут висеть все время и в бесконечном цикле крутиться пока клиент не дисконект то получится что очередь все таки будет
Убежденный
Системный программист
 Аватар для Убежденный
14170 / 6185 / 981
Регистрация: 02.05.2013
Сообщений: 10,294
Завершенные тесты: 1
24.03.2014, 23:05     Многопоточный чат с использованием пула потоков #8
Хм. А что именно будут делать эти потоки в бесконечном цикле ?
И главное - зачем ?
sergeu90
27 / 28 / 3
Регистрация: 17.10.2009
Сообщений: 739
25.03.2014, 01:18  [ТС]     Многопоточный чат с использованием пула потоков #9
Убежденный, они будут ждать от клиента действий и опять зысыпать,а как чат сделать тогда иначе?
Убежденный
Системный программист
 Аватар для Убежденный
14170 / 6185 / 981
Регистрация: 02.05.2013
Сообщений: 10,294
Завершенные тесты: 1
25.03.2014, 09:25     Многопоточный чат с использованием пула потоков #10
sergeu90, очень советую - найдите книгу "Программирование в
сетях Windows", почитайте в ней главу про модели сокетного ввода-вывода,
особенно что касается портов завершения (IOCP). Там вовсю
используются пулы потоков и характерные "примочки", которые с
ними связаны. Многие такие вопросы сами собой отпадут.
aLarman
636 / 557 / 89
Регистрация: 13.12.2012
Сообщений: 2,109
25.03.2014, 10:32     Многопоточный чат с использованием пула потоков #11
Цитата Сообщение от sergeu90 Посмотреть сообщение
они будут ждать от клиента действий и опять зысыпать,а как чат сделать тогда иначе?
использовать асинхронный ввод вывод, а не в цикле ждать когда удаленная сторона что то сделает,
на сокете появилась активность на чтение - читаем
писать как правило можно всегда, во время дисконнекта по моим наблюдениям появляется активность на чтение, но recv вернет 0 (0 может вернуть и в других ситуациях, важно при получении 0 байт проверить значение errno/WSAGetLastError())
sergeu90
27 / 28 / 3
Регистрация: 17.10.2009
Сообщений: 739
25.03.2014, 13:34  [ТС]     Многопоточный чат с использованием пула потоков #12
aLarman, ну я трошки не понимаю,как сделать асинхронный ввод вывод,я так и собирался делать в цикле бесконечном ждать активности от клиента,а как вот сделать иначе сложно)

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

Добавлено через 1 минуту
aLarman, а можно пример кода примитивный самый простой что бы понять как это выглядит так сложно разобраться,ели не сложно не большой пример
aLarman
636 / 557 / 89
Регистрация: 13.12.2012
Сообщений: 2,109
25.03.2014, 13:45     Многопоточный чат с использованием пула потоков #15
Цитата Сообщение от sergeu90 Посмотреть сообщение
и как тогда со стороны клиента держать соеденение что бы не отсоеденяться от сервера
что Вы планируете использовать? UDP или TCP
sergeu90
27 / 28 / 3
Регистрация: 17.10.2009
Сообщений: 739
25.03.2014, 13:48  [ТС]     Многопоточный чат с использованием пула потоков #16
aLarman, планирую использовать TCP и хочу вот сделать что-нибудь на курсовой вроде как чата,но вот через пул потоков,для начала мне бы понять как вы сказали активность смотреть и в пул передавать

Добавлено через 1 минуту
aLarman, тоесть в пул я знаю как передавать,я собираюсь использовать winapi функции для работы с пулом
aLarman
636 / 557 / 89
Регистрация: 13.12.2012
Сообщений: 2,109
25.03.2014, 13:50     Многопоточный чат с использованием пула потоков #17
вот пример с 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 клиента
sergeu90
27 / 28 / 3
Регистрация: 17.10.2009
Сообщений: 739
25.03.2014, 13:53  [ТС]     Многопоточный чат с использованием пула потоков #18
aLarman, получается это не пул тут я так понял ?
aLarman
636 / 557 / 89
Регистрация: 13.12.2012
Сообщений: 2,109
25.03.2014, 13:58     Многопоточный чат с использованием пула потоков #19
да, в методе Dispatch там где вызывается
C++
1
ProcessRead(sock);
заменить на добавление задачи в пул, и соответственно в AddClient не создавать потоки для каждого клиента (эти потоки используются для получение ввода, и отправки сообщений клиенту - реализация не самая ровная потому что там есть блокирующий вызов - вызов cin)
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.03.2014, 14:00     Многопоточный чат с использованием пула потоков
Еще ссылки по теме:

Поиск в бинарном файле с использованием файловых потоков C++
C++ Вызов конструктора и деструктора с использованием пула
Создать многопоточный таймер C++

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

Или воспользуйтесь поиском по форуму:
sergeu90
27 / 28 / 3
Регистрация: 17.10.2009
Сообщений: 739
25.03.2014, 14:00  [ТС]     Многопоточный чат с использованием пула потоков #20
aLarman, спасибо начну разбираться на днях)
Yandex
Объявления
25.03.2014, 14:00     Многопоточный чат с использованием пула потоков
Ответ Создать тему
Опции темы

Текущее время: 22:57. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru