Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.79/58: Рейтинг темы: голосов - 58, средняя оценка - 4.79
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 26

Сокеты, одновременная работа с несколькими клиентами !!!

26.02.2012, 21:31. Показов 12414. Ответов 52
Метки нет (Все метки)

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

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

Возможно существует какой-нибудь простой класс для сокитов под линукс, чтобы можно было создать сокет, добавить к нему функцию обрабатывающую событие поступления нового сообщения от клиентов, и функцию ответа клиенту по его id номеру.

В си новичок, просьба не пинать. Спасибо!
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
26.02.2012, 21:31
Ответы с готовыми решениями:

Работа QTcpServer с несколькими клиентами
Имеется сервер который напрямую общается с бд(sqlite). К нему одновременно и постоянно подключаются и отключаются(после завершения работы с...

Одновременная работа с несколькими ST-LINK/V2 в IAR
Отлаживаю 3 отдельных устройства, который работают в одной связке. Соответственно запущено 3 IAR-a, в которых правится разный код. Прошить...

сессии и одновременная работа под несколькими пользователями
Возникла необходимость сделать чтобы с сайтом можно было работать под несколькими зарегестрироваными пользователими одновременно в...

52
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
27.02.2012, 03:57
Цитата Сообщение от Kirm Посмотреть сообщение
Что нужно сделать?
линковать прогу с библиотеками boost. как, в прочем, и с любыми другими библиотеками.

Добавлено через 3 минуты
asio - header-only библиотека. ее линковать с прогой не надо. только boost_system.

> g++ program.cpp -oprogram -lboost_system
0
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 26
27.02.2012, 04:11  [ТС]
g++ /home/me/server/main.cpp -oprogram -l/usr/include/boost/

пишет cannot find -l/usr/include/boost/
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
27.02.2012, 04:27
Цитата Сообщение от Kirm Посмотреть сообщение
-l/usr/include/boost/
и что это по твоему такое?
ключик "-l" я же показал как использовать.

почитай "man g++", главу Linker Options.
0
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 26
27.02.2012, 04:29  [ТС]
g++ /home/me/server/main.cpp -oprogram -lboost_system

тоже самое пишет
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
27.02.2012, 04:36
скопируй сюда сообщение компилятора. ибо писать "cannot find -l/usr/include/boost/" компилятор не может при использовании "-l" (латинская L в нижнем регистре)
0
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 26
27.02.2012, 04:40  [ТС]
g++ /home/me/server/main.cpp -oprogram -lboost_system

/usr/bin/ld: cannot find -lboost_system
collect2: выполнение ld завершилось с кодом возврата 1
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
27.02.2012, 04:46
покажи вывод команды "ls -l /usr/lib/libboost*"

Добавлено через 26 секунд
какой дистр используешь?
0
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 26
27.02.2012, 04:49  [ТС]
Ubuntu 11.10 самый обычный дистриб с офф сайта
Вот результат:

-rw-r--r-- 1 root root 107996 2011-06-04 01:54 /usr/lib/libboost_date_time.a
lrwxrwxrwx 1 root root 20 2011-06-04 01:54 /usr/lib/libboost_date_time-mt.a -> libboost_date_time.a
lrwxrwxrwx 1 root root 28 2011-06-04 01:54 /usr/lib/libboost_date_time-mt.so -> libboost_date_time.so.1.46.1
lrwxrwxrwx 1 root root 28 2011-06-04 01:54 /usr/lib/libboost_date_time.so -> libboost_date_time.so.1.46.1
-rw-r--r-- 1 root root 59056 2011-06-04 01:54 /usr/lib/libboost_date_time.so.1.46.1
-rw-r--r-- 1 root root 92096 2011-06-04 01:54 /usr/lib/libboost_iostreams.so.1.46.1
-rw-r--r-- 1 root root 2038312 2011-06-04 01:54 /usr/lib/libboost_regex.a
lrwxrwxrwx 1 root root 16 2011-06-04 01:54 /usr/lib/libboost_regex-mt.a -> libboost_regex.a
lrwxrwxrwx 1 root root 24 2011-06-04 01:54 /usr/lib/libboost_regex-mt.so -> libboost_regex.so.1.46.1
lrwxrwxrwx 1 root root 24 2011-06-04 01:54 /usr/lib/libboost_regex.so -> libboost_regex.so.1.46.1
-rw-r--r-- 1 root root 988412 2011-06-04 01:54 /usr/lib/libboost_regex.so.1.46.1
-rw-r--r-- 1 root root 993228 2011-06-04 01:54 /usr/lib/libboost_serialization.a
lrwxrwxrwx 1 root root 24 2011-06-04 01:54 /usr/lib/libboost_serialization-mt.a -> libboost_serialization.a
lrwxrwxrwx 1 root root 32 2011-06-04 01:54 /usr/lib/libboost_serialization-mt.so -> libboost_serialization.so.1.46.1
lrwxrwxrwx 1 root root 32 2011-06-04 01:54 /usr/lib/libboost_serialization.so -> libboost_serialization.so.1.46.1
-rw-r--r-- 1 root root 420256 2011-06-04 01:54 /usr/lib/libboost_serialization.so.1.46.1
-rw-r--r-- 1 root root 693438 2011-06-04 01:54 /usr/lib/libboost_wserialization.a
lrwxrwxrwx 1 root root 25 2011-06-04 01:54 /usr/lib/libboost_wserialization-mt.a -> libboost_wserialization.a
lrwxrwxrwx 1 root root 33 2011-06-04 01:54 /usr/lib/libboost_wserialization-mt.so -> libboost_wserialization.so.1.46.1
lrwxrwxrwx 1 root root 33 2011-06-04 01:54 /usr/lib/libboost_wserialization.so -> libboost_wserialization.so.1.46.1
-rw-r--r-- 1 root root 301188 2011-06-04 01:54 /usr/lib/libboost_wserialization.so.1.46.1
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
27.02.2012, 04:54
ты не установил библиотеку boost.system.

выполни "sudo apt-get install libboost-dev"
0
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 26
27.02.2012, 04:56  [ТС]
Пишет уже установлена самая новая версия. Удалить все это дело и заново поставить?
Сделал autoremove и твою команду, всё равно нету boost.system и не компилирует, таже ошибка
Может нужно версию старее установить?
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
27.02.2012, 04:59
нет.
выполни "sudo apt-get install libboost-system-dev"
1
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 26
27.02.2012, 05:08  [ТС]
Так с систем получилось, но вот теперь такой
ответ
g++ /home/kirill/server/server/main.cpp -oprogram -lboost_system
/tmp/ccx9OiY8.o: In function `boost::asio::detail::posix_tss_ptr_create(unsigned int&)':
main.cpp:(.text._ZN5boost4asio6detail20posix_tss_ptr_createERj[boost::asio::detail::posix_tss_ptr_create(unsigned int&)]+0x15): undefined reference to `pthread_key_create'
/tmp/ccx9OiY8.o: In function `boost::asio::detail::posix_tss_ptr<boost::asio::detail::call_stack<boost::asio::detail::task_io_service>::context>::~posix_tss_ptr()':
main.cpp:(.text._ZN5boost4asio6detail13posix_tss_ptrINS1_10call_stackINS1_15task_io_serviceEE7contextEED2Ev[_ZN5boost4asio6detail13posix_tss_ptrINS1_10call_stackINS1_15task_io_serviceEE7contextEED5Ev]+0xf): undefined reference to `pthread_key_delete'
/tmp/ccx9OiY8.o: In function `boost::asio::detail::posix_tss_ptr<boost::asio::detail::call_stack<boost::asio::detail::strand_service::strand_impl>::context>::~posix_tss_ptr()':
main.cpp:(.text._ZN5boost4asio6detail13posix_tss_ptrINS1_10call_stackINS1_14strand_service11strand_implEE7contextEED2Ev[_ZN5boost4asio6detail13posix_tss_ptrINS1_10call_stackINS1_14strand_service11strand_implEE7contextEED5Ev]+0xf): undefined reference to `pthread_key_delete'
collect2: выполнение ld завершилось с кодом возврата 1

 Комментарий модератора 
Подобные полотна - под кат!

Код программы:

C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <boost/asio.hpp>
 
using namespace std;
 
int main()
{
    cout << "Hello world!" << endl;
    return 0;
}
 Комментарий модератора 
Используйте теги форматирования кода!
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
27.02.2012, 05:11
компилить так:
> g++ program.cpp -oprogram -lboost_system -lpthread
1
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 26
27.02.2012, 05:23  [ТС]
Получилось! Спасибо огромнейшее!!!

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

Вот что пишет
g++ /home/kirill/server/server/main.cpp -oprogram -lboost_system -lpthread
/tmp/ccMqchnl.o: In function `main':
main.cpp:(.text+0x63): undefined reference to `boost::thread::hardware_concurrency()'
/tmp/ccMqchnl.o: In function `boost::detail::thread_data_base::thread_data_base()':
main.cpp:(.text._ZN5boost6detail16thread_data_baseC2Ev[_ZN5boost6detail16thread_data_baseC5Ev]+0x1a): undefined reference to `vtable for boost::detail::thread_data_base'
/tmp/ccMqchnl.o: In function `boost::detail::interruption_checker::interruption_checker(pthread_mutex_t*, pthread_cond_t*)':
main.cpp:(.text._ZN5boost6detail20interruption_checkerC2EP15pthread_mutex_tP14pthread_cond_t[_ZN5boost6detail20interruption_checkerC5EP15pthread_mutex_tP14pthread_cond_t]+0x8): undefined reference to `boost::detail::get_current_thread_data()'
/tmp/ccMqchnl.o: In function `boost::condition_variable::wait(boost::unique_lock<boost::mutex>&)':
main.cpp:(.text._ZN5boost18condition_variable4waitERNS_11unique_lockINS_5mutexEEE[boost::condition_variable::wait(boost::unique_lock<boost::mutex>&)]+0x83): undefined reference to `boost::this_thread::interruption_point()'
/tmp/ccMqchnl.o: In function `boost::shared_mutex::lock_shared()':
main.cpp:(.text._ZN5boost12shared_mutex11lock_sharedEv[boost::shared_mutex::lock_shared()]+0xe): undefined reference to `boost::this_thread::disable_interruption::disable_interruption()'
main.cpp:(.text._ZN5boost12shared_mutex11lock_sharedEv[boost::shared_mutex::lock_shared()]+0x83): undefined reference to `boost::this_thread::disable_interruption::~disable_interruption()'
main.cpp:(.text._ZN5boost12shared_mutex11lock_sharedEv[boost::shared_mutex::lock_shared()]+0xa5): undefined reference to `boost::this_thread::disable_interruption::~disable_interruption()'
/tmp/ccMqchnl.o: In function `boost::shared_mutex::lock()':
main.cpp:(.text._ZN5boost12shared_mutex4lockEv[boost::shared_mutex::lock()]+0xe): undefined reference to `boost::this_thread::disable_interruption::disable_interruption()'
main.cpp:(.text._ZN5boost12shared_mutex4lockEv[boost::shared_mutex::lock()]+0x82): undefined reference to `boost::this_thread::disable_interruption::~disable_interruption()'
main.cpp:(.text._ZN5boost12shared_mutex4lockEv[boost::shared_mutex::lock()]+0xa4): undefined reference to `boost::this_thread::disable_interruption::~disable_interruption()'
/tmp/ccMqchnl.o: In function `boost::thread_group::~thread_group()':
main.cpp:(.text._ZN5boost12thread_groupD2Ev[_ZN5boost12thread_groupD5Ev]+0x48): undefined reference to `boost::thread::~thread()'
/tmp/ccMqchnl.o: In function `boost::thread_group::join_all()':
main.cpp:(.text._ZN5boost12thread_group8join_allEv[boost::thread_group::join_all()]+0x59): undefined reference to `boost::thread::join()'
/tmp/ccMqchnl.o: In function `boost::thread::thread<boost::_bi::bind_t<unsigned int, boost::_mfi::mf0<unsigned int, boost::asio::io_service>, boost::_bi::list1<boost::_bi::value<boost::asio::io_service*> > > >(boost::_bi::bind_t<unsigned int, boost::_mfi::mf0<unsigned int, boost::asio::io_service>, boost::_bi::list1<boost::_bi::value<boost::asio::io_service*> > >, boost::disable_if<boost::is_convertible<boost::_bi::bind_t<unsigned int, boost::_mfi::mf0<unsigned int, boost::asio::io_service>, boost::_bi::list1<boost::_bi::value<boost::asio::io_service*> > >&, boost::detail::thread_move_t<boost::_bi::bind_t<unsigned int, boost::_mfi::mf0<unsigned int, boost::asio::io_service>, boost::_bi::list1<boost::_bi::value<boost::asio::io_service*> > > > >, boost::thread::dummy*>::type)':
main.cpp:(.text._ZN5boost6threadC2INS_3_bi6bind_tIjNS_4_mfi3mf0IjNS_4asio10io_serviceEEENS2_5list1INS2_5valueIPS7_EEEEEEEET_NS_10disable_ifINS_14is_convertibleIRSF_NS_6detail13thread_move_tISF_EEEEPNS0_5dummyEE4typeE[_ZN5boost6threadC5INS_3_bi6bind_tIjNS_4_mfi3mf0IjNS_4asio10io_serviceEEENS2_5list1INS2_5valueIPS7_EEEEEEEET_NS_10disable_ifINS_14is_convertibleIRSF_NS_6detail13thread_move_tISF_EEEEPNS0_5dummyEE4typeE]+0x31): undefined reference to `boost::thread::start_thread()'
/tmp/ccMqchnl.o: In function `std::auto_ptr<boost::thread>::~auto_ptr()':
main.cpp:(.text._ZNSt8auto_ptrIN5boost6threadEED2Ev[_ZNSt8auto_ptrIN5boost6threadEED5Ev]+0x14): undefined reference to `boost::thread::~thread()'
/tmp/ccMqchnl.o: In function `boost::detail::thread_data<boost::_bi::bind_t<unsigned int, boost::_mfi::mf0<unsigned int, boost::asio::io_service>, boost::_bi::list1<boost::_bi::value<boost::asio::io_service*> > > >::~thread_data()':
main.cpp:(.text._ZN5boost6detail11thread_dataINS_3_bi6bind_tIjNS_4_mfi3mf0IjNS_4asio10io_serviceEEENS2_5list1INS2_5valueIPS7_EEEEEEED2Ev[_ZN5boost6detail11thread_dataINS_3_bi6bind_tIjNS_4_mfi3mf0IjNS_4asio10io_serviceEEENS2_5list1INS2_5valueIPS7_EEEEEEED5Ev]+0x16): undefined reference to `boost::detail::thread_data_base::~thread_data_base()'
/tmp/ccMqchnl.o:(.rodata._ZTIN5boost6detail11thread_dataINS_3_bi6bind_tIjNS_4_mfi3mf0IjNS_4asio10io_serviceEEENS2_5list1INS2_5valueIPS7_EEEEEEEE[typeinfo for boost::detail::thread_data<boost::_bi::bind_t<unsigned int, boost::_mfi::mf0<unsigned int, boost::asio::io_service>, boost::_bi::list1<boost::_bi::value<boost::asio::io_service*> > > >]+0x8): undefined reference to `typeinfo for boost::detail::thread_data_base'
collect2: выполнение ld завершилось с кодом возврата 1
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
27.02.2012, 05:25
> g++ program.cpp -oprogram -lboost_system -lboost_thread -lpthread
1
Модератор
 Аватар для vxg
3409 / 2181 / 354
Регистрация: 13.01.2012
Сообщений: 8,468
27.02.2012, 08:55
делал движок. исходные коды в теме Программирование сокетов, ругается код
0
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 26
27.02.2012, 18:37  [ТС]
Не работает распределение на потоки! В чем дело?


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
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <boost/thread.hpp>
 
/***************************************************************************/
 
// максимальная длина принимаемого сообщения.
static const size_t message_len = 10000;
 
typedef boost::shared_ptr<boost::asio::ip::tcp::socket> socket_ptr;
 
// начало приема запросов на подключение.
void start_accept(
   boost::asio::ip::tcp::acceptor* acceptor
);
 
// создаем асинхронную операцию аксепта.
void on_accept(
   boost::asio::ip::tcp::acceptor* acceptor,
   socket_ptr socket
);
 
// вызовется при подключении.
void on_accept_handler(
   boost::asio::ip::tcp::acceptor* acceptor,
   socket_ptr socket,
   const boost::system::error_code& error // объект ошибки
);
 
// вызовется при завершении асинхронной записи.
void on_async_read(
   socket_ptr socket,
   boost::shared_array<char> message, // shared_array мы сюда передаем для
                                      // того, чтоб не дать ему удалить данные которыми он
                                      // владеет до завершения асинхронной записи.
   const boost::system::error_code& error // объект ошибки
);
 
void on_async_write(
  const boost::system::error_code& error,
  std::size_t bytes_transferred
);
 
 
/***************************************************************************/
 
int main() {
   static const char* ip = "127.0.0.1";
   static const boost::uint16_t port = 44550;
 
   // io_service - основа asio.
   boost::asio::io_service ios;
 
   // объект реализующий "вечную задачу".
   boost::shared_ptr<boost::asio::io_service::work> work(new boost::asio::io_service::work(ios));
 
   // определяем кол-во ядер.
   size_t cpu_count = boost::thread::hardware_concurrency();
 
   // создаем кол-во рабочих потоков равное кол-ву ядер.
   boost::thread_group work_threads;
   for ( size_t idx = 0; idx < cpu_count; ++idx ) {
      work_threads.create_thread(boost::bind(&boost::asio::io_service::run, &ios));
   }
 
   // объект представляющий адрес для TCP соединений.
   boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(ip), port);
 
   // объект акксептора соединений.
   boost::asio::ip::tcp::acceptor acceptor(ios, endpoint);
 
   // запускаем асинхронный прием запросов на подключение
   start_accept(&acceptor);
 
   // сбрасываем "вечную задачу".
   work.reset();
 
   // работаем пока не завершаться все потоки.
   work_threads.join_all();
 
   // завершаемся.
   return 0;
}
 
/***************************************************************************/
 
// создаем асинхронную операцию аксепта
void start_accept(
   boost::asio::ip::tcp::acceptor* acceptor)
{
   // создаем объект сокета который будет связан с принятым подключением.
   socket_ptr socket(new socket_ptr::element_type(acceptor->get_io_service()));
 
   // создаем операци. асинхронного аксепта.
   acceptor->async_accept(
      *socket,
      boost::bind(
         &on_accept_handler,
         acceptor,
         socket,
         boost::asio::placeholders::error
      )
   );
}
 
// вызовется при приеме нового подключения.
void on_accept_handler(
   boost::asio::ip::tcp::acceptor* acceptor,
   socket_ptr socket,
   const boost::system::error_code& error)
{
   if ( !error ) {
      // создаем shared_array который должен жить вплоть до окончании асинхронного чтения.
      // для этого, message передаем как аргумент в функциональный объект, для того, чтоб инкрементировать счетчик ссылок.
      boost::shared_array<char> message(new char[message_len]);
 
      // для принятого соединения запускаем операцию асинхронного чтения.
      boost::asio::async_read(
         *socket,
         boost::asio::buffer(message.get(), message_len),
         boost::asio::transfer_at_least(2),
         boost::bind(
            &on_async_read,
            socket,
            message,
            boost::asio::placeholders::error
         )
      );
   } else {
      std::cout << "on_accept_handler() error: " << error.message() << std::endl;
   }
 
   // снова запускаем асинхронный прием запросов на подключение
   start_accept(acceptor);
}
 
/***************************************************************************/
 
// вызовется при завершении асинхронного чтения.
 
// примечание: аргумент message и socket, разрушаться при выходе из функции.
void on_async_read(
   socket_ptr socket,
   boost::shared_array<char> message,
   const boost::system::error_code& error)
{
   if ( !error ) {
      std::cout << "received message: " << message.get() << std::endl;
 
       char answer[10] = "ALL OK!!!";
       int g = 500;
       for (int i=0; i<2000000000; i++) {
            g=g*g;
            g=g*g;
            g=g*g;
       }
 
       boost::asio::async_write(
         *socket,
         boost::asio::buffer(answer, 10),
         on_async_write
      );
 
 
   } else {
      std::cout << "on_async_read() error: " << error.message() << std::endl;
   }
}
 
 
void on_async_write(const boost::system::error_code& error, std::size_t bytes_transferred) {
 
///
 
};
 
/***************************************************************************/
 Комментарий модератора 
Используйте теги форматирования кода!

cpu_count равен 2, пробовал выводить, тоесть должно 2 потока быть.
В функции чтения сделал небольшой нагрузочный тест на 10 сек. чтобы имитировать нагрузку на проц. Выполняется он примерно за 10с. Так вот, когда подключаются одновременно клиент1 и клиент2, на сервере выводится только сообщение от первого клиента, и только через 10с. сообщение от второго. Ответ получает клиент1 через 10с, клиент2 через 20с.

Что не так? И еще, можно ли сделать, чтобы boost::asio::async_write не вызывал handler, мне отслеживать событие приемки данных клиентом не нужно.

Добавлено через 4 часа 3 минуты
Протестил, и понял вроде бы он не хочет открывать доступ второму клиенту пока работа с первым не завершена. Если я делаю так в on_accept_handler когда подключен один клиент:

ios.post(boost:bind(&adding_work, socket));
ios.post(boost:bind(&adding_work, socket));

то обе функции выполняются одновременно, а если так при двух клиентах:

ios.post(boost:bind(&adding_work, socket));

то он начала обрабатывает одного, и только потом начинает второго
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
28.02.2012, 12:39
Цитата Сообщение от Kirm Посмотреть сообщение
когда подключаются одновременно клиент1 и клиент2, на сервере выводится только сообщение от первого клиента, и только через 10с. сообщение от второго. Ответ получает клиент1 через 10с, клиент2 через 20с.
такое возможно, только если используется один поток. у тебя же их два.

либо я не правильно тебя понял...

код:
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
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <boost/thread.hpp>
 
/***************************************************************************/
 
// максимальная длина принимаемого сообщения.
static const size_t message_len = 32;
 
typedef boost::shared_ptr<boost::asio::ip::tcp::socket> socket_ptr;
 
// начало приема запросов на подключение.
void start_accept(
   boost::asio::ip::tcp::acceptor* acceptor
);
 
// вызовется при подключении.
void on_accept_handler(
   boost::asio::ip::tcp::acceptor* acceptor,
   socket_ptr socket,
   const boost::system::error_code& error // объект ошибки
);
 
// вызовется при завершении асинхронной записи.
void on_async_read(
   socket_ptr socket,
   boost::shared_array<char> message, // shared_array мы сюда передаем для
                                      // того, чтоб не дать ему удалить данные которыми он
                                      // владеет до завершения асинхронной записи.
   const boost::system::error_code& error, // объект ошибки
   std::size_t bytes_transferred
);
 
void on_async_write(
   socket_ptr socket,
   const boost::system::error_code& error,
   std::size_t bytes_transferred
);
 
/***************************************************************************/
 
int main() {
   static const char* ip = "127.0.0.1";
   static const boost::uint16_t port = 44550;
 
   // io_service - основа asio.
   boost::asio::io_service ios;
 
   // объект реализующий "вечную задачу".
   boost::shared_ptr<boost::asio::io_service::work> work(new boost::asio::io_service::work(ios));
 
   // определяем кол-во ядер.
   //size_t cpu_count = boost::thread::hardware_concurrency();
   size_t cpu_count = 2;
 
   // создаем кол-во рабочих потоков равное кол-ву ядер.
   boost::thread_group work_threads;
   for ( size_t idx = 0; idx < cpu_count; ++idx ) {
      work_threads.create_thread(boost::bind(&boost::asio::io_service::run, &ios));
   }
 
   // объект представляющий адрес для TCP соединений.
   boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(ip), port);
 
   // объект акксептора соединений.
   boost::asio::ip::tcp::acceptor acceptor(ios, endpoint);
 
   // запускаем асинхронный прием запросов на подключение
   start_accept(&acceptor);
 
   // сбрасываем "вечную задачу".
   work.reset();
 
   // работаем пока не завершаться все потоки.
   work_threads.join_all();
 
   // завершаемся.
   return 0;
}
 
/***************************************************************************/
 
// создаем асинхронную операцию аксепта
void start_accept(
   boost::asio::ip::tcp::acceptor* acceptor)
{
   // создаем объект сокета который будет связан с принятым подключением.
   socket_ptr socket(new socket_ptr::element_type(acceptor->get_io_service()));
 
   // создаем операци. асинхронного аксепта.
   acceptor->async_accept(
      *socket,
      boost::bind(
         &on_accept_handler,
         acceptor,
         socket,
         boost::asio::placeholders::error
      )
   );
}
 
// вызовется при приеме нового подключения.
void on_accept_handler(
   boost::asio::ip::tcp::acceptor* acceptor,
   socket_ptr socket,
   const boost::system::error_code& error)
{
   if ( !error ) {
      std::cout << "new connection from " << socket->remote_endpoint() << std::endl;
      // создаем shared_array который должен жить вплоть до окончании асинхронного чтения.
      // для этого, message передаем как аргумент в функциональный объект, для того, чтоб инкрементировать счетчик ссылок.
      boost::shared_array<char> message(new char[message_len]);
 
      // для принятого соединения запускаем операцию асинхронного чтения.
      boost::asio::async_read(
         *socket,
         boost::asio::buffer(message.get(), message_len),
         boost::asio::transfer_at_least(2),
         boost::bind(
            on_async_read,
            socket,
            message,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred
         )
      );
   } else {
      std::cout << "on_accept_handler() error: " << error.message() << std::endl;
   }
 
   // снова запускаем асинхронный прием запросов на подключение
   start_accept(acceptor);
}
 
/***************************************************************************/
 
// вызовется при завершении асинхронного чтения.
 
// примечание: аргумент message и socket, разрушаться при выходе из функции.
void on_async_read(
   socket_ptr socket,
   boost::shared_array<char> message,
   const boost::system::error_code& error,
   std::size_t bytes_transferred)
{
   if ( !error ) {
      message[bytes_transferred] = 0;
      std::cout << "received message: " << message.get() << std::endl;
      sleep(10); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 
      boost::asio::async_write(
         *socket,
         boost::asio::buffer("reply!"),
         boost::bind(
            on_async_write,
            socket,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred
         )
      );
 
   } else {
      std::cout << "on_async_read() error: " << error.message() << std::endl;
   }
}
 
/***************************************************************************/
 
void on_async_write(
   socket_ptr socket,
   const boost::system::error_code& error,
   std::size_t bytes_transferred)
{
   std::cout << "on_async_write(): e: " << error << ", writen: " << bytes_transferred << std::endl;
 
   boost::shared_array<char> message(new char[message_len]);
 
   // для принятого соединения запускаем операцию асинхронного чтения.
   boost::asio::async_read(
      *socket,
      boost::asio::buffer(message.get(), message_len),
      boost::asio::transfer_at_least(2),
      boost::bind(
         &on_async_read,
         socket,
         message,
         boost::asio::placeholders::error,
         boost::asio::placeholders::bytes_transferred
      )
   );
}
 
/***************************************************************************/
http://liveworkspace.org/code/... a6eaa0a3d2

я жестко установил два рабочих потока.

чтение от клиентов, как и отправка ответов - происходит параллельно. а вот если произошло чтение от двух клиентов - то два потока заняты, и аксепт нового подключения произойдет только когда завершится ожидание на любом от клиентов.
0
0 / 0 / 0
Регистрация: 26.02.2012
Сообщений: 26
28.02.2012, 16:00  [ТС]
Полностью скопировал код, за исключение того, что в функции:

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
void on_async_write(
   socket_ptr socket,
   const boost::system::error_code& error,
   std::size_t bytes_transferred)
{
   std::cout << "on_async_write(): e: " << error << ", writen: " << bytes_transferred << std::endl;
 
   boost::shared_array<char> message(new char[message_len]);
 
   /*
   // для принятого соединения запускаем операцию асинхронного чтения.
   boost::asio::async_read(
      *socket,
      boost::asio::buffer(message.get(), message_len),
      boost::asio::transfer_at_least(2),
      boost::bind(
         &on_async_read,
         socket,
         message,
         boost::asio::placeholders::error,
         boost::asio::placeholders::bytes_transferred
      )
   );
   */
}
Чтобы после ответа клиенту, сервер завершал коннект.

Запускаю программу.
Для проверки запускаю через браузер практически одновременно два экзэмпляра php скрипта, который через сокеты коннектится, отправляет сообщение, читает, выводит на экран и завершается. Первый выводbn ответ через 10с, второй через 20с. после запуска. Если бы работал паралельный прием клиентов, то оба должны были вывести ответ через 10с. Что не так?
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
28.02.2012, 16:16
прежде чем запостить код - я проверил.
но проверял я telnet`ом.

1. запускаю сервер.
2. подключаюсь два телнета.
3. в обоих пишу что нибуть и жму ентер.
4. запускаю третий телнет на подключение. он ожидает пока не закончится любая одна задача.

Цитата Сообщение от Kirm Посмотреть сообщение
два экзэмпляра php скрипта
можешь показать скрипт?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
28.02.2012, 16:16

Одновременная работа с XML файлом несколькими людьми
Как одновременно работа с XML файлом нескольким людям? (и как это по научному называется?) И второй вопрос который интересует меня...

сервер чата с несколькими клиентами
вот код чата //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner)...

Совет по работе с несколькими TCP клиентами
Всем привет. У меня возникло некоторое недопонимание как работать с несколькими TCP клиентами. Может просто дико туплю. В общем есть...

Программа синхронизации папок по сети с несколькими клиентами
Здравствуйте! Помогите,пожалуйста с задачей. Мне нужно написать программу синхронизации папок по сети с несколькими...

Одновременная запись в файл несколькими потоками
Всем привет! Продолжаю разбираться с многопоточностью. Собственно вопрос в теме. Программа пишет лог. Каждый поток в ходе выполнения...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
24 Мат модель здравосохранения: функциональные требования к строительству пищеблока
anaschu 18.06.2026
СРесурсами1: финансовый SD-контур, калькулятор функциональных требований пищеблока Сегодня разделили затраты в агенте Экономика по образцу модели НАСОСЫ, добавили расчёт ROI и построили первый. . .
23. что сделано за последнее время.
anaschu 17.06.2026
• Эталон: Клиника НИИ питания РАМН, Москва — централизованный пищеблок, 225 коек, 180 пациентов • Git: репозиторий med2, ветка абсентеизм. Рабочий файл: СРесурсами1_v4. alp • Смежный проект:. . .
22. Подключение слоя системной динамики (потоковые диффуры): экономические метрики модели
anaschu 17.06.2026
Апдейт модели: финансовый контур, разделение затрат Продолжаю развивать модель рабочего коллектива на AnyLogic. В этот раз работа шла над агентом Экономика — финансовым SD-слоем модели. Задача:. . .
[golang] Insert Delete GetRandom O(1) (Leetcode: 380)
alhaos 16.06.2026
Insert Delete GetRandom O(1) Сложность: Medium Источник: LeetCode 380 Задача Реализовать структуру данных RandomizedSet, которая поддерживает следующие операции за O(1) в среднем:
Свет в конце тоннеля
kumehtar 16.06.2026
Поймал себя на одной мысли. Раньше мне всегда казалось неправильным жить без чёткого понимания, куда всё идёт. Будто я иду по дороге судьбы, но не знаю, куда она ведёт. А раз не знаю — значит,. . .
[golang] Реализация стека с поддержкой получения минимального элемента за O(1)
alhaos 16.06.2026
Min Stack Сложность: Medium Источник: LeetCode 155 Задача: Реализовать стек который поддерживает push, pop, top и получение минимального элемента за O(1). Методы:
[golang] Конкурентный fetcher с ограничением максимального количества одновременных HTTP запросов.
alhaos 10.06.2026
Задача Реализовать конкурентный fetcher с ограничением максимального количества одновременных HTTP запросов. Сигнатура func Fetch(urls string, maxConcurrent int) Result Пример urls :=. . .
[golang] Состояние гонки (race condition)
alhaos 10.06.2026
Состояние гонки (race condition) Состояние гонки (Race Condition) — это ошибка, возникающая при одновременном доступе нескольких горутин к одним и тем же данным без должной синхронизации. При этом. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru