sample/filter/c2.cpp

00001 /*
00002   Клиент #2.
00003 
00004   Получает запросы сервера и отсылает серверу ответы.
00005 
00006   Демонстрирует возможность запуска SObjectizer-а на вспомогательной
00007   нити и проведения диалога с пользователем на контексте главной нити.
00008 */
00009 
00010 #include <iostream>
00011 #include <memory>
00012 
00013 #include <threads_1/h/threads.hpp>
00014 
00015 #include <so_4/rt/h/rt.hpp>
00016 #include <so_4/rt/h/msg_auto_ptr.hpp>
00017 
00018 #include <so_4/socket/channels/h/channels.hpp>
00019 #include <so_4/rt/comm/h/a_cln_channel.hpp>
00020 
00021 #include <so_4/api/h/api.hpp>
00022 
00023 #include <so_4/api/h/api.hpp>
00024 
00025 #include <so_4/timer_thread/simple/h/pub.hpp>
00026 #include <so_4/disp/active_obj/h/pub.hpp>
00027 
00028 #include "c2i.hpp"
00029 
00030 //
00031 // Класс агента клиента #2.
00032 //
00033 class a_cln_t :
00034   public so_4::rt::agent_t
00035 {
00036   typedef so_4::rt::agent_t base_type_t;
00037   public :
00038     a_cln_t();
00039     virtual ~a_cln_t();
00040 
00041     virtual const char *
00042     so_query_type() const;
00043 
00044     virtual void
00045     so_on_subscription();
00046 
00047     // Имя единственного агента этого типа в приложении.
00048     static const std::string &
00049     agent_name();
00050 
00051     // Реакция на появление агента в системе.
00052     void
00053     evt_start();
00054 
00055     // Реакция на запрос сервера.
00056     void
00057     evt_server_request(
00058       const c2i_t::msg_request * );
00059 };
00060 
00061 SOL4_CLASS_START( a_cln_t )
00062 
00063   SOL4_EVENT( evt_start )
00064 
00065   SOL4_EVENT_STC(
00066     evt_server_request,
00067     c2i_t::msg_request )
00068 
00069   SOL4_STATE_START( st_normal )
00070     SOL4_STATE_EVENT( evt_start )
00071     SOL4_STATE_EVENT( evt_server_request )
00072   SOL4_STATE_FINISH()
00073 
00074 SOL4_CLASS_FINISH()
00075 
00076 a_cln_t::a_cln_t()
00077   :
00078     base_type_t( agent_name().c_str() )
00079 {
00080   // Делаем агента активным объектом.
00081   so_add_traits( so_4::disp::active_obj::
00082     query_active_obj_traits() );
00083 }
00084 
00085 a_cln_t::~a_cln_t()
00086 {
00087 }
00088 
00089 void
00090 a_cln_t::so_on_subscription()
00091 {
00092   // Подписываем те события, инциденты для которых
00093   // в системе уже существуют.
00094 
00095   so_subscribe( "evt_start",
00096     so_4::rt::sobjectizer_agent_name(), "msg_start" );
00097 
00098 }
00099 
00100 const std::string &
00101 a_cln_t::agent_name()
00102 {
00103   static std::string name( "a_cln_t" );
00104   return name;
00105 }
00106 
00107 void
00108 a_cln_t::evt_start()
00109 {
00110   // Агент стартовал.
00111 
00112   // Нужно зарегистрировать глобального агента и
00113   // подписаться на его сообщение.
00114   so_4::ret_code_t rc = so_4::api::make_global_agent(
00115     c2i_t::agent_name(),
00116     c2i_t::agent_type() );
00117   if( rc )
00118     std::cerr << rc << std::endl;
00119   else
00120     so_subscribe( "evt_server_request",
00121       c2i_t::agent_name(), "msg_request" );
00122 }
00123 
00124 void
00125 a_cln_t::evt_server_request(
00126   const c2i_t::msg_request * )
00127 {
00128   std::cout << "Request from server" << std::endl;
00129   so_4::api::send_msg( c2i_t::agent_name(),
00130     "msg_reply", 0 );
00131 }
00132 
00133 // Создание кооперации, в которую входит главный агент
00134 // клиента #2 и коммуникационный агент (клиентский сокет).
00135 void
00136 create_coop(
00137   // Адрес серверного сокета.
00138   const char * sock_addr )
00139 {
00140   a_cln_t * a_cln = new a_cln_t();
00141 
00142   // Создание клиентского сокета для взаимодействия по SOP.
00143   // Фильтр, который допускает только сообщения агента c2i.
00144   so_4::sop::std_filter_t * filter =
00145     so_4::sop::create_std_filter();
00146   filter->insert( c2i_t::agent_name() );
00147 
00148   so_4::rt::comm::a_cln_channel_t * a_sock =
00149     new so_4::rt::comm::a_cln_channel_t(
00150       "a_sock",
00151       so_4::socket::channels::create_client_factory( sock_addr ),
00152       // Назначаем фильтр.
00153       filter,
00154       // Назначаем обработчик разрывов связи.
00155       so_4::rt::comm::a_cln_channel_base_t::create_def_disconnect_handler(
00156         5000, 0 )
00157     );
00158   // Сокет так же будет активным агентом.
00159   so_4::disp::active_obj::make_active( *a_sock );
00160   // Поскольку трафик предполагается небольшой, то устанавливаем
00161   // порог так, чтобы сообщения уходили сразу же.
00162   a_sock->set_out_threshold( so_4::rt::comm::threshold_t( 1, 1 ) );
00163 
00164   so_4::rt::agent_t * agents[] =
00165   {
00166     a_cln, a_sock
00167   };
00168   so_4::rt::dyn_agent_coop_helper_t coop_helper(
00169     new so_4::rt::dyn_agent_coop_t(
00170       "client_coop", agents,
00171       sizeof( agents ) / sizeof( agents[ 0 ] ) ) );
00172 
00173   if( coop_helper.result() )
00174     std::cerr << "register_coop:\n"
00175       << coop_helper.result() << std::endl;
00176 }
00177 
00178 // Уничтожение клиентской кооперации.
00179 void
00180 destroy_coop()
00181 {
00182   so_4::ret_code_t rc =
00183     so_4::api::deregister_coop( "client_coop" );
00184   if( rc )
00185     std::cerr << "deregister_coop:\n" << rc << std::endl;
00186 }
00187 
00188 //
00189 // Нить, на которой будет происходить запуск SObjectizer-а
00190 //
00191 class sobj_thread_t :
00192   public threads_1::thread_t
00193 {
00194   public :
00195     sobj_thread_t();
00196     virtual ~sobj_thread_t();
00197 
00198   protected :
00199     virtual void
00200     body();
00201 };
00202 
00203 sobj_thread_t::sobj_thread_t()
00204 {
00205 }
00206 
00207 sobj_thread_t::~sobj_thread_t()
00208 {
00209 }
00210 
00211 void
00212 sobj_thread_t::body()
00213 {
00214   std::auto_ptr< so_4::timer_thread::timer_thread_t >
00215     timer_ptr( so_4::timer_thread::simple::create_timer_thread() );
00216 
00217   std::auto_ptr< so_4::rt::dispatcher_t >
00218     disp_ptr( so_4::disp::active_obj::create_disp( *timer_ptr ) );
00219 
00220   so_4::ret_code_t rc = so_4::api::start( *disp_ptr, 0 );
00221   if( rc )
00222   {
00223     std::cerr << "start: " << rc << std::endl;
00224   }
00225 }
00226 
00227 int
00228 main( int argc, char ** argv )
00229 {
00230   if( 2 == argc )
00231   {
00232     sobj_thread_t thread;
00233     thread.start();
00234 
00235     // Засыпаем, чтобы дать стартовать SObjectizer.
00236     // Это самый простой способ синхронизации с sobj_thread_t.
00237     threads_1::sleep_thread( 1000 );
00238 
00239     bool is_continue = true;
00240     while( is_continue )
00241     {
00242       std::string choice;
00243 
00244       std::cout << "Choose action:\n"
00245         "\t0 - quit\n"
00246         "\t1 - create client coop\n"
00247         "\t2 - destroy client coop\n> "
00248         << std::flush;
00249 
00250       std::cin >> choice;
00251 
00252       if( choice == "0" )
00253       {
00254         // Завершаем работу.
00255         so_4::api::send_msg(
00256           so_4::rt::sobjectizer_agent_name(),
00257           "msg_normal_shutdown", 0,
00258           so_4::rt::sobjectizer_agent_name() );
00259         is_continue = false;
00260       }
00261       else if( choice == "1" )
00262         // Создаем кооперацию клиента.
00263         create_coop( argv[ 1 ] );
00264       else if( choice == "2" )
00265         // Уничтожаем кооперацию клиента.
00266         destroy_coop();
00267     }
00268 
00269     // Ожидаем завершения SObjectizer.
00270     thread.wait();
00271 
00272     return 0;
00273   }
00274   else
00275   {
00276     std::cerr << "sample_filter_c2 <server_sock_addr>"
00277       << std::endl;
00278 
00279     return -1;
00280   }
00281 }

Документация по SObjectizer. Последние изменения: Thu Jan 12 10:52:50 2006. Создано системой  doxygen 1.4.6-NO
Hosted by uCoz