На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
    > Помогите разобраться boost::asio , решил переписать сетевую часть на бусте
      К сожалению буст для меня это непонятный темный лес.
      Нужен ваш хелп.

      Сервер у меня многопоточный. Но я правильно понимаю что объект boost::asio::io_service должен быть один единственный в приложении?
      В каждом потоке достаточно вызвать io_service.run();

      правильно?

      Тут у меня возникает первая затыка. Которую я пока не знаю как решить.
      Мне необходимо в каждой асинхронной операции будь то чтение или запись знать в каком потоке она вызвалась.

      у меня имеется обертка над потоком - свой класс workerThread.
      При старте сервера я создаю ХХХ объектов workerThread и у каждого такая потоковая функция
      ExpandedWrap disabled
        void    workerThreads::workingThread( )
        {
            server s( io_service, m_serverport );
            io_service.run();
        }
      Сообщение отредактировано: progman -
        Вызывай GetCurrentThreadId(). Или тебе нужен конкретный указатель на объект workerThread? Тогда можно сделать глобальную мапу ThreadId -> workerThread
          Или так:
          ExpandedWrap disabled
            __declspec(thread) workerThreads* WorkerThread = nullptr;
            ...
            void    workerThreads::workingThread( )
            {
                WorkerThread = this;
             
                server s( io_service, m_serverport );
                io_service.run();
            }
            Цитата Pacific @
            Вызывай GetCurrentThreadId(). Или тебе нужен конкретный указатель на объект workerThread? Тогда можно сделать глобальную мапу ThreadId -> workerThread

            Я к этому "решению" и пришел.

            ExpandedWrap disabled
                  workerThread** m_threadsmap = NULL;    
                  m_threadsmap = new LPWORKERTHREADPTR[ 0x10000 ];
                  memset( m_threadsmap, 0, sizeof(LPWORKERTHREADPTR) * 0x10000 );

            и заношу в массив указатель на потоковый объект по его id перерасход памяти есть но зато мгновенный доступ в отличие от std::map
            ExpandedWrap disabled
                  for (int i = 0; i < numberOfThreads; i++)
                  {
                      workerThread* th = new workerThread( m_dbpool, io_service );        
                      int threadid = th->createThread( getServerPort());      
                      m_threadsmap[ threadid ] = th;
                  }


            Я сделал "опасное" допущение что ID потока в 32 битной windows не превысит 0хFFFF - лично я ни разу не сталкивался чтобы оно было больше 0x4000

            далее в одном и потоков куда меня коллбэк boost.asio выкинул такой вот код:
            ExpandedWrap disabled
                  int threadid        = GetCurrentThreadId();
                  workerThread* th    = m_threadsmap[ threadid ];


            вопрос в том - насколько по корану данный сабж. и не является ли мега кривыми костыялми. может быть у буста есть фича чтобы в коллбэк передать какие то данные о потоке в котором он вызвался.
            Сообщение отредактировано: progman -
              progman
              Это костыль, да. Лучше переделай на thread local глобальную переменную (пост №3) - доступ также мгновенный, только перерасхода памяти не будет, и не будет зависеть от предположений о threadid.
                Цитата Pacific @
                progman
                Это костыль, да. Лучше переделай на thread local глобальную переменную (пост №3) - доступ также мгновенный, только перерасхода памяти не будет, и не будет зависеть от предположений о threadid.

                че то я туплю - как мне оно поможет?
                ExpandedWrap disabled
                  __declspec(thread) workerThreads* WorkerThread = nullptr;
                  ...
                  void    workerThreads::workingThread( )
                  {
                      WorkerThread = this;
                   
                      server s( io_service, m_serverport );
                      io_service.run();
                  }

                ?
                  progman
                  WorkerThread будет глобальной переменной, но своей для каждого потока. Где надо - получай указатель на свой объект, локальный для текущего потока.
                    Решили соскочить с IOCP на буст? :D
                    Интересный опыт, поделитесь потом своим мнением - такое сравнение будет очень полезно для всех. :yes:
                      Цитата Oleg2004 @
                      Решили соскочить с IOCP на буст? :D
                      Интересный опыт, поделитесь потом своим мнением - такое сравнение будет очень полезно для всех. :yes:

                      под виндой boost::asio через IOCP и работает.

                      Добавлено
                      еще момент, комильфо ли отсылать данные клиенту так:
                      ExpandedWrap disabled
                        HRESULT connection::send( char* buffer, DWORD length, LPWSAOVERLAPPED lpOverlapped )
                        {
                            auto self(shared_from_this());
                            boost::asio::async_write( m_socket, boost::asio::buffer(&length, header_length), [this, self](boost::system::error_code ec, std::size_t /*length*/)
                            {
                                if (!ec)
                                {
                         
                                }
                            });
                         
                            boost::asio::async_write( m_socket, boost::asio::buffer( buffer, length), [this, self](boost::system::error_code ec, std::size_t /*length*/)
                            {
                                if (!ec)
                                {
                         
                                }
                            });
                         
                            return S_OK;
                        }

                      сначала шлю 4 байта размер а потом данные.
                      в WSASend можно было два буфера указать и отправить за один вызов. Там оно более эстетично в коде.
                      А как в бусте поэстетичнее?
                      И я надеюсь тут я асинхронную передачу данных делаю :-)
                        Цитата progman @
                        В каждом потоке достаточно вызвать io_service.run();

                        правильно?

                        Да.
                        Цитата progman @
                        Мне необходимо в каждой асинхронной операции будь то чтение или запись знать в каком потоке она вызвалась.

                        boost::this_thread::get_id()
                        ?

                        Добавлено
                        Цитата progman @
                        А как в бусте поэстетичнее?

                        Никогда так не делал. Затрудняюсь сказать, обеспечивает ли буст последовательность исполнения команд из очереди на нескольких потоках. Лучше в обработчике завершения первого write пошли второй. И, скати, почему нельзя отправить сразу 1м пакетом?
                        Сообщение отредактировано: shm -
                          Цитата shm @
                          Никогда так ты не делал. Затрудняюсь сказать, обеспечивает ли буст последовательность исполнения команд из очереди на нескольких потоках.

                          по идее оно в одном потоке вызывается.
                          сейчас запустил тест - 15 тысяч клиентов третий час нормально пашут.

                          но что то тоже стали сомнения терзать.
                          Хотя с другой стороны мне важно чтобы сначала ушел заголовок пакета - просто 4 байта а потом тело.
                          И не важно из одного потока или из разных. по идее это гарантируется последовательным вызовом... но что там внутри... уже сомнения пошли

                          Цитата shm @
                          Лучше в обработчике завершения первого write пошли второй.

                          придется выделять память и хранить передаваемый буфер.
                          Сообщение отредактировано: progman -
                            Цитата progman @
                            boost::asio через IOCP

                            Ну да:
                            ExpandedWrap disabled
                              #if defined(BOOST_ASIO_HAS_IOCP)
                              #include <boost/scoped_ptr.hpp>
                              #include <boost/asio/io_service.hpp>
                              #include <boost/asio/detail/mutex.hpp>
                              #include <boost/asio/detail/op_queue.hpp>
                              #include <boost/asio/detail/socket_types.hpp>
                              #include <boost/asio/detail/timer_op.hpp>
                              #include <boost/asio/detail/timer_queue_base.hpp>
                              #include <boost/asio/detail/timer_queue_fwd.hpp>
                              #include <boost/asio/detail/timer_queue_set.hpp>
                              #include <boost/asio/detail/win_iocp_io_service_fwd.hpp>
                              #include <boost/asio/detail/win_iocp_operation.hpp>
                              #include <boost/asio/detail/thread.hpp>
                              #include <boost/asio/detail/push_options.hpp>

                            Такое нагромождение всего чего - не, я лично сторонник АПИ.
                            Все библиотеки подобного рода - это инструмент для RAD (rapid application development)
                            Быстро сбацать и запустить.
                            Очень даже возможно, что и будет неплохо работать - для определенных целей.
                            И, как нам всем понятно - внутри классов буста - все тот же виндовский АПИ...
                            Впрочем это все только ИМХО.
                            Вот тут интересные мысли - вроде по теме.
                            И кстати о проблеме - протокол вида "frame_size->frame_body"
                            Сообщение отредактировано: Oleg2004 -
                              Посмотрел, последовательность в твоем случае будет соблюдена. Обратил еще раз внимание на твой код, вот так:
                              Цитата progman @
                              boost::asio::buffer(&length, header_length)

                              делать нельзя. Т. к. должна обеспечиваться гарантия существования объекта до завершения операции. Другими словами, boost::asio::buffer работает по ссылке.

                              Добавлено
                              Цитата progman @
                              придется выделять память и хранить передаваемый буфер.

                              Ты так говоришь как будто это так сложно организовать.
                              Сообщение отредактировано: shm -
                                Цитата shm @
                                делать нельзя. Т. к. должна обеспечиваться гарантия существования объекта до завершения операции. Другими словами, boost::asio::buffer работает по ссылке.

                                спасибо. не учел. Думал там копирование внутри.
                                ExpandedWrap disabled
                                      HRESULT connection::send( char* buffer, DWORD length, LPWSAOVERLAPPED lpOverlapped )
                                      {
                                          char* sendbuffer = new char[length + header_length];
                                          memcpy( &sendbuffer[ 0 ], &length, header_length);
                                          memcpy( &sendbuffer[ header_length ], buffer, length );
                                   
                                          boost::asio::async_write( m_socket, boost::asio::buffer( sendbuffer, length + header_length ),
                                              std::bind( &connection::handle_write, shared_from_this(), sendbuffer, std::placeholders::_1, std::placeholders::_2 ) );
                                          
                                          return S_OK;
                                      }
                                   
                                      void connection::handle_write(char* buffer, const boost::system::error_code& a_error, std::size_t a_size)
                                      {
                                          delete[] buffer;
                                      }
                                  Я у себя привязывал буфер данных чтения и записи к объекту, связанному с сокетом. Не скажу, что это самый правильный подход, но рабочий.
                                    С чтением вопрос. Гарантирует ли такая конструкция буста что я получу на выходе все данные которые ожидаю получить?
                                    ExpandedWrap disabled
                                      void connection::do_read_body( int datalength )
                                      {
                                          auto self( shared_from_this( ) );
                                              
                                          m_socket.async_read_some(boost::asio::buffer(m_recvbuffer, datalength), [this, self](boost::system::error_code ec, std::size_t length)
                                          {
                                              if( !ec )
                                              {
                                                  //is datalength ==  length ?????
                                              }
                                          }
                                      }


                                    + есть непонятка как остановить io_service прервав во всех потоках прием данных и ожидание коннекта
                                    io_service.stop() не обеспечивает остановку всего
                                    Сообщение отредактировано: progman -
                                      Цитата progman @
                                      Гарантирует ли такая конструкция буста что я получу на выходе все данные которые ожидаю получить?

                                      Цитата http://www.boost.org/doc/libs/1_38_0/doc/h..._read_some.html
                                      The read operation may not read all of the requested number of bytes. Consider using the async_read function if you need to ensure that the requested amount of data is read before the asynchronous operation completes.


                                      Добавлено
                                      Цитата progman @
                                      не обеспечивает остановку всего

                                      Что это значит? У меня все работает, только нужно дождаться завершения потоков, где вызвана io_sevice.run().
                                      Сообщение отредактировано: Oleg2004 -
                                        Цитата shm @
                                        Что это значит? У меня все работает, только нужно дождаться завершения потов, где вызвана io_sevice.run().

                                        у меня после вызова io_service.stop() крашится все где то внутри буста
                                          Цитата progman @
                                          у меня после вызова io_service.stop() крашится все где то внутри буста

                                          Как потоки создаешь?
                                            Цитата shm @
                                            Цитата progman @
                                            у меня после вызова io_service.stop() крашится все где то внутри буста

                                            Как потоки создаешь?

                                            ExpandedWrap disabled
                                               hWorkerThread = CreateThread( NULL, 0, serverPool, this, 0, &dwThreadId );


                                            ExpandedWrap disabled
                                              DWORD WINAPI workerThread::serverPool( LPVOID lpvParam )
                                              {
                                                  return (( workerThread* )lpvParam)->thread();
                                              }
                                               
                                              int workerThread::thread( )
                                              {
                                                  mWorkerThread = this;
                                               
                                                  try
                                                  {
                                                      server s( m_dbpool, io_service, m_serverport );
                                                      
                                                      io_service.run();
                                                  }
                                               
                                                  catch (std::exception& e)
                                                  {
                                                      std::cerr << "Exception: " << e.what() << "\n";
                                                  }
                                               
                                                  return 0;
                                              }
                                              Цитата progman @
                                              CreateThread

                                              попробуй заменить на _beginthreadex. А еще лучше на boost::thread, тогда переходник serverPool и не нужен будет.
                                                progman, решил проблему?
                                                  Цитата shm @
                                                  progman, решил проблему?

                                                  нет (
                                                  у меня на сервере #include <boost/thread.hpp> вызывает кучу ошибок в компиляции ( windows web server 2008 R2 ) - я приложение собираю на удаленном сервере который полностью идентичен рабочим серверам пула.
                                                  при этом на моей локальной машине ( windows 10 ) все ок.
                                                  Студия в обоих случаях 2013 professional
                                                  Boost билдился с одинаковыми параметрами.

                                                  Поскольку критической важности нету я пока забил - занимаюсь текучкой ( дрючу оболтусов своих :crazy: а то расслабились )
                                                  Будет время нагуглю как решать траблу а то даже в X-COM 2 поиграть некогда (((

                                                  Скрытый текст
                                                  1> workerThread.cpp
                                                  1>C:\SERVER\LIBS\boost_1_60_0\boost/type_traits/common_type.hpp(111): fatal error C1001: An internal error has occurred in the compiler.
                                                  1> (compiler file 'f:\dd\vctools\compiler\cxxfe\sl\p1\c\esumem.c', line 8636)
                                                  1> To work around this problem, try simplifying or changing the program near the locations listed above.
                                                  1> Please choose the Technical Support command on the Visual C++
                                                  1> Help menu, or open the Technical Support help file for more information
                                                  1> C:\SERVER\LIBS\boost_1_60_0\boost/type_traits/common_type.hpp(133) : see reference to class template instantiation 'boost::type_traits_detail::common_type_impl<T1,T2>' being compiled
                                                  1> with
                                                  1> [
                                                  1> T1=int_least64_t
                                                  1> , T2=int_least64_t
                                                  1> ]
                                                  1> C:\SERVER\LIBS\boost_1_60_0\boost/type_traits/common_type.hpp(139) : see reference to class template instantiation 'boost::type_traits_detail::common_type_decay_helper<T1,T2,__int64,__int64>' being compiled
                                                  1> with
                                                  1> [
                                                  1> T1=int_least64_t
                                                  1> , T2=int_least64_t
                                                  1> ]
                                                  1> C:\SERVER\LIBS\boost_1_60_0\boost/chrono/duration.hpp(405) : see reference to class template instantiation 'boost::common_type<Rep1,Rep2>' being compiled
                                                  1> with
                                                  1> [
                                                  1> Rep1=int_least64_t
                                                  1> , Rep2=int_least64_t
                                                  1> ]
                                                  1> C:\SERVER\LIBS\boost_1_60_0\boost/thread/win32/basic_timed_mutex.hpp(211) : see reference to class template instantiation 'boost::common_type<boost::chrono::system_clock::duration,boost::chrono::system_clock::duration>' being compiled
                                                  1> SendingList.cpp
                                                  1>c1xx : fatal error C1060: compiler is out of heap space
                                                  1> Note: non-fatal system error releasing memory (87)
                                                  1> basePacket.cpp
                                                  1>c1xx : fatal error C1060: compiler is out of heap space
                                                  1> Note: non-fatal system error releasing memory (87)
                                                  1> tcpConnectionList.cpp
                                                  1>c1xx : fatal error C1060: compiler is out of heap space
                                                  1> Note: non-fatal system error releasing memory (87)
                                                  1> tcp_server.cpp
                                                  1>c1xx : fatal error C1060: compiler is out of heap space
                                                  1> Note: non-fatal system error releasing memory (87)
                                                  1> NotifycationThreads.cpp
                                                  1>c1xx : fatal error C1060: compiler is out of heap space
                                                  1> Note: non-fatal system error releasing memory (87)
                                                  Сообщение отредактировано: progman -
                                                    progman, судя по всему баг VC. Попробуй накати все обновления.
                                                      Цитата shm @
                                                      progman, судя по всему баг VC. Попробуй накати все обновления.

                                                      уже. MSVC 2013 Update 4 требуется.
                                                      обновил. Бага исчезла но все равно падает буст когда стоплю.
                                                      вот код:
                                                      ExpandedWrap disabled
                                                        void CCompletitionPort::closeServer()
                                                        {
                                                            io_service.stop();
                                                            ::WaitForMultipleObjects( m_threadsEvents.size(), &m_threadsEvents[ 0 ], TRUE, INFINITE);
                                                        }

                                                      Логика простая - в каждом потоке создаю эвент который дергаю когда поток заканчивает работу.
                                                      после остановки сервиса жду когда все потоки закончатся.
                                                      Но падает все где то в недрах буста (
                                                      ни один поток не заканчивается.

                                                      поэтому сейчас вот такой вот криворукое решение:
                                                      ExpandedWrap disabled
                                                        void CCompletitionPort::closeServer()
                                                        {
                                                            exit(0);
                                                        }

                                                      :fool:
                                                        Цитата progman @
                                                        ::WaitForMultipleObjects( m_threadsEvents.size(), &m_threadsEvents[ 0 ], TRUE, INFINITE);

                                                        wtf? Если ты используешь буст, то там у объекта thread есть метот join для этих целей.

                                                        Добавлено
                                                        Цитата progman @
                                                        Но падает все где то в недрах буста (

                                                        Падает как? Буст кидает эксепшен? И где конкретно падает, стек вызовов-то хоть есть?
                                                        Сообщение отредактировано: shm -
                                                          Цитата shm @
                                                          Падает как? Буст кидает эксепшен? И где конкретно падает, стек вызовов-то хоть есть?

                                                          да эксепшен
                                                          Цитата
                                                          Unhandled exception at 0x00089DA6 in servervisuald.exe: 0xC0000005: Access violation reading location 0x08B8F7B0.


                                                          вот стек:
                                                          Цитата
                                                          > servervisuald.exe!boost::asio::basic_io_object<boost::asio::socket_acceptor_service<boost::asio::ip::tcp>,1>::get_service() Line 209 C++
                                                          servervisuald.exe!boost::asio::basic_socket_acceptor<boost::asio::ip::tcp,boost::asio::socket_acceptor_service<boost::asio::ip::tcp> >::async_accept<boost::asio::ip::tcp,boost::asio::stream_socket_service<boost::asio::ip::tcp>,boost::_bi::bind_t<void,void (__cdecl*)(network::server *,int,boost::system::error_code const &),boost::_bi::list3<boost::_bi::value<network::server *>,boost::_bi::value<int>,boost::arg<1> > > >(boost::asio::basic_socket<boost::asio::ip::tcp,boost::asio::stream_socket_service<boost::asio::ip::tcp> > & peer, boost::_bi::bind_t<void,void (__cdecl*)(network::server *,int,boost::system::error_code const &),boost::_bi::list3<boost::_bi::value<network::server *>,boost::_bi::value<int>,boost::arg<1> > > && handler, void * __formal) Line 1019 C++
                                                          servervisuald.exe!network::server::accept(int id, const boost::system::error_code & err) Line 39 C++
                                                          servervisuald.exe!network::server::handle_accept(network::server * srv, int id, const boost::system::error_code & err) Line 29 C++
                                                          servervisuald.exe!boost::_bi::list3<boost::_bi::value<network::server *>,boost::_bi::value<int>,boost::arg<1> >::operator()<void (__cdecl*)(network::server *,int,boost::system::error_code const &),boost::_bi::rrlist1<boost::system::error_code const &> >(boost::_bi::type<void> __formal, void (network::server *, int, const boost::system::error_code &) * & f, boost::_bi::rrlist1<boost::system::error_code const &> & a, int __formal) Line 398 C++
                                                          servervisuald.exe!boost::_bi::bind_t<void,void (__cdecl*)(network::server *,int,boost::system::error_code const &),boost::_bi::list3<boost::_bi::value<network::server *>,boost::_bi::value<int>,boost::arg<1> > >::operator()<boost::system::error_code const &>(const boost::system::error_code & a1) Line 1235 C++
                                                          servervisuald.exe!boost::asio::detail::binder1<boost::_bi::bind_t<void,void (__cdecl*)(network::server *,int,boost::system::error_code const &),boost::_bi::list3<boost::_bi::value<network::server *>,boost::_bi::value<int>,boost::arg<1> > >,boost::system::error_code>::operator()() Line 48 C++
                                                          servervisuald.exe!boost::asio::asio_handler_invoke<boost::asio::detail::binder1<boost::_bi::bind_t<void,void (__cdecl*)(network::server *,int,boost::system::error_code const &),boost::_bi::list3<boost::_bi::value<network::server *>,boost::_bi::value<int>,boost::arg<1> > >,boost::system::error_code> >(boost::asio::detail::binder1<boost::_bi::bind_t<void,void (__cdecl*)(network::server *,int,boost::system::error_code const &),boost::_bi::list3<boost::_bi::value<network::server *>,boost::_bi::value<int>,boost::arg<1> > >,boost::system::error_code> & function, ...) Line 70 C++
                                                          servervisuald.exe!boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::binder1<boost::_bi::bind_t<void,void (__cdecl*)(network::server *,int,boost::system::error_code const &),boost::_bi::list3<boost::_bi::value<network::server *>,boost::_bi::value<int>,boost::arg<1> > >,boost::system::error_code>,boost::_bi::bind_t<void,void (__cdecl*)(network::server *,int,boost::system::error_code const &),boost::_bi::list3<boost::_bi::value<network::server *>,boost::_bi::value<int>,boost::arg<1> > > >(boost::asio::detail::binder1<boost::_bi::bind_t<void,void (__cdecl*)(network::server *,int,boost::system::error_code const &),boost::_bi::list3<boost::_bi::value<network::server *>,boost::_bi::value<int>,boost::arg<1> > >,boost::system::error_code> & function, boost::_bi::bind_t<void,void (__cdecl*)(network::server *,int,boost::system::error_code const &),boost::_bi::list3<boost::_bi::value<network::server *>,boost::_bi::value<int>,boost::arg<1> > > & context) Line 37 C++
                                                          servervisuald.exe!boost::asio::detail::win_iocp_socket_accept_op<boost::asio::basic_socket<boost::asio::ip::tcp,boost::asio::stream_socket_service<boost::asio::ip::tcp> >,boost::asio::ip::tcp,boost::_bi::bind_t<void,void (__cdecl*)(network::server *,int,boost::system::error_code const &),boost::_bi::list3<boost::_bi::value<network::server *>,boost::_bi::value<int>,boost::arg<1> > > >::do_complete(boost::asio::detail::win_iocp_io_service * owner, boost::asio::detail::win_iocp_operation * base, const boost::system::error_code & result_ec, unsigned int __formal) Line 142 C++
                                                          servervisuald.exe!boost::asio::detail::win_iocp_operation::complete(boost::asio::detail::win_iocp_io_service & owner, const boost::system::error_code & ec, unsigned int bytes_transferred) Line 46 C++
                                                          servervisuald.exe!boost::asio::detail::win_iocp_io_service::do_one(bool block, boost::system::error_code & ec) Line 406 C++
                                                          servervisuald.exe!boost::asio::detail::win_iocp_io_service::run(boost::system::error_code & ec) Line 164 C++
                                                          servervisuald.exe!boost::asio::io_service::run() Line 59 C++
                                                          servervisuald.exe!network::workerThread::workingThread() Line 59 C++


                                                          Добавлено
                                                          Цитата shm @
                                                          wtf? Если ты используешь буст, то там у объекта thread есть метот join для этих целей.

                                                          ну а как я еще в другом потоке узнаю что все рабочие потоки закончились - имхо только через в каждом потоке SetEvent + WaitForMultipleObjects
                                                          я же говорю буст я практически не знаю. А усиленно разбираться нету времени (

                                                          Цитата Oleg2004 @
                                                          Пару слов - как впечатление...Все думаю тоже скачать и попробовать любимую игру в новом виде...Кстати у вас стимовский вариант?

                                                          не знаю. На стиме купил но играть некогда.
                                                            Цитата progman @
                                                            ну а как я еще в другом потоке узнаю что все рабочие потоки закончились - имхо только через в каждом потоке SetEvent + WaitForMultipleObjects

                                                            ExpandedWrap disabled
                                                              io_service.stop();
                                                              for(auto th : ThreadList)
                                                              {
                                                                 th->join();
                                                                 delete th;
                                                              }

                                                            ???

                                                            Добавлено
                                                            Цитата progman @
                                                            servervisuald.exe!network::server::accept(int id, const boost::system::error_code & err) Line 39 C++
                                                            servervisuald.exe!network::server::handle_accept(network::server * srv, int id, const boost::system::error_code & err) Line 29 C++

                                                            твое? что там понаписано?

                                                            Добавлено
                                                            Складывается впечатление, что завершается accept с ошибкой и ты ее некорректно обрабатываешь. Хотя может я и ошибаюсь, так сложно сказать.
                                                            Сообщение отредактировано: shm -
                                                              вот полный код всей сетевой части:
                                                              ExpandedWrap disabled
                                                                void    workerThread::workingThread( )
                                                                {
                                                                    mWorkerThread = this;
                                                                 
                                                                    try
                                                                    {
                                                                        server s( m_dbpool, io_service, m_serverport );
                                                                        
                                                                        io_service.run();
                                                                    }
                                                                 
                                                                    catch (std::exception& e)
                                                                    {
                                                                        std::cerr << "Exception: " << e.what() << "\n";
                                                                    }
                                                                 
                                                                    ::SetEvent( m_closeThreadEvent );
                                                                 
                                                                    return;
                                                                }


                                                              ExpandedWrap disabled
                                                                    server::server(  dbPool&    dbpool, boost::asio::io_service& io_service, short port)
                                                                        : m_acceptor( io_service, tcp::endpoint( tcp::v4( ), port ) )
                                                                        , m_socket( io_service )
                                                                        , m_dbpool( dbpool )
                                                                    {
                                                                        m_acceptor.async_accept( m_socket, boost::bind( handle_accept, this, 0, _1 ) );
                                                                    }
                                                                 
                                                                server::~server()
                                                                {
                                                                    
                                                                }
                                                                 
                                                                void server::handle_accept( server* srv, int id, const boost::system::error_code & err )
                                                                {
                                                                    srv->accept( id, err );
                                                                }
                                                                 
                                                                void server::accept( int id, const boost::system::error_code & err )
                                                                {
                                                                    if (!err)
                                                                    {
                                                                        std::make_shared<connection>( m_dbpool, std::move( m_socket ) )->accept();
                                                                    }
                                                                 
                                                                    m_acceptor.async_accept( m_socket, boost::bind( handle_accept, this, 0, _1 ) );
                                                                }


                                                              ExpandedWrap disabled
                                                                const int CLIENT_TIMEOUT = 3600;
                                                                 
                                                                    connection::connection( dbPool& dbpool, tcp::socket socket ) :  m_socket(std::move(socket))
                                                                        , m_dbpool(dbpool)
                                                                    {
                                                                        m_pClient       = NULL;
                                                                        m_inactivetime  = 0;
                                                                    }
                                                                 
                                                                    connection::~connection()
                                                                    {
                                                                        //m_pClient will be destroy inside
                                                                        if (_S(net::ClientList) )
                                                                            _S(net::ClientList)->remove(this);
                                                                    }
                                                                 
                                                                    void connection::update(float dt)
                                                                    {
                                                                        m_inactivetime += dt;
                                                                 
                                                                        if (m_inactivetime >= CLIENT_TIMEOUT)
                                                                            closeSocket();
                                                                    }
                                                                 
                                                                    void connection::closeSocket()
                                                                    {
                                                                        m_socket.close();
                                                                    }
                                                                 
                                                                    HRESULT connection::send( char* buffer, DWORD length )
                                                                    {
                                                                        m_inactivetime = 0;
                                                                 
                                                                        char* sendbuffer = new char[length + header_length];
                                                                        memcpy( &sendbuffer[ 0 ], &length, header_length);
                                                                        memcpy( &sendbuffer[ header_length ], buffer, length );
                                                                 
                                                                        boost::asio::async_write( m_socket, boost::asio::buffer( sendbuffer, length + header_length ),
                                                                            std::bind( &connection::handle_write, shared_from_this(), sendbuffer, std::placeholders::_1, std::placeholders::_2 ) );
                                                                            
                                                                        return S_OK;
                                                                    }
                                                                 
                                                                    HRESULT connection::sendPolicy()
                                                                    {
                                                                        const char mCrossDomainPolicy[] = "<?xml version=\"1.0\"?>\r\n<!DOCTYPE cross-domain-policy SYSTEM \"/xml/dtds/cross-domain-policy.dtd\">\r\n<cross-domain-policy>\r\n<allow-access-from domain=\"*\" to-ports=\"1-31111\" />\r\n</cross-domain-policy>";
                                                                        const int length = strlen(mCrossDomainPolicy);
                                                                 
                                                                        char* sendbuffer = new char[ length ];
                                                                        memcpy( &sendbuffer[0], mCrossDomainPolicy, length );
                                                                 
                                                                        boost::asio::async_write(m_socket, boost::asio::buffer( sendbuffer, length ),
                                                                            std::bind(&connection::handle_write, shared_from_this(), sendbuffer, std::placeholders::_1, std::placeholders::_2));
                                                                 
                                                                        return S_OK;
                                                                    }
                                                                 
                                                                    void connection::handle_write(char* buffer, const boost::system::error_code& a_error, std::size_t a_size)
                                                                    {
                                                                        delete[] buffer;
                                                                    }
                                                                 
                                                                    void connection::accept()
                                                                    {
                                                                        m_inactivetime = 0;
                                                                 
                                                                        m_pClient = new Client( this, m_dbpool.getDataBase(dbPool::system), m_dbpool.getDataBase(dbPool::logi), m_dbpool.getDataBase(dbPool::tickets ) );
                                                                        
                                                                        m_pClient->onConnect( m_socket.remote_endpoint().address().to_v4().to_ulong() );
                                                                 
                                                                        _S(net::ClientList)->push( this );
                                                                 
                                                                        do_read_header( );
                                                                    }
                                                                 
                                                                    void connection::do_read_header()
                                                                    {
                                                                        m_inactivetime = 0;
                                                                 
                                                                        auto self( shared_from_this( ) );
                                                                 
                                                                        m_socket.async_read_some(boost::asio::buffer(m_recvbuffer, header_length), [this, self](boost::system::error_code ec, std::size_t length)
                                                                        {
                                                                            if( !ec )
                                                                            {
                                                                                int bodylength = ((int*)m_recvbuffer)[0];
                                                                                
                                                                                if (bodylength > 0 && bodylength < max_length)
                                                                                {
                                                                                    do_read_body( bodylength );
                                                                                }
                                                                                else
                                                                                {
                                                                                    const char mPolicyFileRequest[] = "<policy-file-request/>";
                                                                                    if ( 'lop<' == bodylength )
                                                                                    {
                                                                                        do_read_body( static_cast< unsigned int > (strlen( mPolicyFileRequest ) - PROTOCOL_HEADER_SIZE) );
                                                                                    }
                                                                                    else
                                                                                        m_socket.close();
                                                                                }
                                                                 
                                                                            }
                                                                        } );
                                                                    }
                                                                 
                                                                    
                                                                    void connection::do_read_body( int datalength )
                                                                    {
                                                                        m_inactivetime = 0;
                                                                 
                                                                        auto self( shared_from_this( ) );
                                                                        
                                                                        m_socket.async_read_some(boost::asio::buffer( m_recvbuffer, datalength ), [this, self](boost::system::error_code ec, std::size_t length)
                                                                        {
                                                                            if( !ec )
                                                                            {
                                                                                if ( 18 == length && checkPoliciFileRequest( m_recvbuffer ) )
                                                                                {
                                                                                    
                                                                                    this->sendPolicy();
                                                                 
                                                                                    return;
                                                                                }
                                                                                else
                                                                                {                  
                                                                                    
                                                                                    
                                                                                    HRESULT hr = m_pClient->onReceiveBlock((unsigned char*)m_recvbuffer, length);
                                                                 
                                                                 
                                                                                    if (S_OK == hr)
                                                                                    {
                                                                                        do_read_header();
                                                                                    }
                                                                 
                                                                                    if (S_DISCONNECT == hr)
                                                                                        m_socket.close();
                                                                                }
                                                                            }
                                                                        } );
                                                                 
                                                                    }
                                                                Цитата progman @
                                                                void server::accept( int id, const boost::system::error_code & err )
                                                                {
                                                                if (!err)
                                                                {
                                                                std::make_shared<connection>( m_dbpool, std::move( m_socket ) )->accept();
                                                                }

                                                                m_acceptor.async_accept( m_socket, boost::bind( handle_accept, this, 0, _1 ) );
                                                                }

                                                                Скорее всего бага тут. Попробуй добавь для отладки проверку флага завершения:
                                                                ExpandedWrap disabled
                                                                  void server::accept( int id, const boost::system::error_code & err )
                                                                  {
                                                                      if(TerminateFlag)
                                                                          return;
                                                                      if (!err)
                                                                      {
                                                                          std::make_shared<connection>( m_dbpool, std::move( m_socket ) )->accept();
                                                                      }
                                                                   
                                                                      m_acceptor.async_accept( m_socket, boost::bind( handle_accept, this, 0, _1 ) );
                                                                  }
                                                                  ...
                                                                  TerminateFlag = false;
                                                                  io_service.stop();
                                                                  Цитата shm @
                                                                  Цитата progman @
                                                                  void server::accept( int id, const boost::system::error_code & err )
                                                                  {
                                                                  if (!err)
                                                                  {
                                                                  std::make_shared<connection>( m_dbpool, std::move( m_socket ) )->accept();
                                                                  }

                                                                  m_acceptor.async_accept( m_socket, boost::bind( handle_accept, this, 0, _1 ) );
                                                                  }

                                                                  Скорее всего бага тут. Попробуй добавь для отладки проверку флага завершения:
                                                                  ExpandedWrap disabled
                                                                    void server::accept( int id, const boost::system::error_code & err )
                                                                    {
                                                                        if(TerminateFlag)
                                                                            return;
                                                                        if (!err)
                                                                        {
                                                                            std::make_shared<connection>( m_dbpool, std::move( m_socket ) )->accept();
                                                                        }
                                                                     
                                                                        m_acceptor.async_accept( m_socket, boost::bind( handle_accept, this, 0, _1 ) );
                                                                    }
                                                                    ...
                                                                    TerminateFlag = false;
                                                                    io_service.stop();

                                                                  спасибо - флаг помог
                                                                  посылаю лучи респекта. :rolleyes:
                                                                    progman, это не решение - это просто проверка, что ошибка тут. Проверяй причину ошибки, т. к. баг тут:
                                                                    Цитата progman @
                                                                    m_acceptor.async_accept( m_socket, boost::bind( handle_accept, this, 0, _1 ) );

                                                                    нельзя так делать при остановке io_service. Можешь проверять код ошибки. Также у io_service есть метод bool stopped().

                                                                    Добавлено
                                                                    И перепиши ожидание потоков.
                                                                    Сообщение отредактировано: shm -
                                                                      progman, ping. До ума-то будешь доводить? Складывается впечатление, что мне эта тема интереснее, чем тебе :wacko:
                                                                        shm
                                                                        У него небось работы невпроворот... :D
                                                                        Труд, мир, май...
                                                                          Цитата shm @
                                                                          progman, ping. До ума-то будешь доводить? Складывается впечатление, что мне эта тема интереснее, чем тебе :wacko:

                                                                          костыли работают - глубоко копать правда нет времени от слова совсем (((
                                                                            Цитата progman @
                                                                            костыли работают - глубоко копать правда нет времени от слова совсем (((

                                                                            Это неправильный подход.
                                                                            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                            0 пользователей:


                                                                            Рейтинг@Mail.ru
                                                                            [ Script execution time: 0,1019 ]   [ 17 queries used ]   [ Generated: 28.03.24, 19:31 GMT ]