sample/filter/c1.cpp

00001 /*
00002   Клиент #1.
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 "c1i.hpp"
00029 
00030 //
00031 // Класс агента клиента #1.
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     // запрос серверу.
00053     struct  msg_send_request
00054     {
00055     };
00056 
00057     // Реакция на появление агента в системе.
00058     void
00059     evt_start();
00060 
00061     // Реакция на команду отсылки запроса серверу.
00062     void
00063     evt_send_request(
00064       const msg_send_request * );
00065 
00066     // Реакция на ответ сервера.
00067     void
00068     evt_server_reply(
00069       const c1i_t::msg_reply * );
00070 };
00071 
00072 SOL4_CLASS_START( a_cln_t )
00073 
00074   SOL4_MSG_START( msg_send_request,
00075     a_cln_t::msg_send_request )
00076   SOL4_MSG_FINISH()
00077 
00078   SOL4_EVENT( evt_start )
00079 
00080   SOL4_EVENT_STC(
00081     evt_send_request,
00082     a_cln_t::msg_send_request )
00083 
00084   SOL4_EVENT_STC(
00085     evt_server_reply,
00086     c1i_t::msg_reply )
00087 
00088   SOL4_STATE_START( st_normal )
00089     SOL4_STATE_EVENT( evt_start )
00090     SOL4_STATE_EVENT( evt_send_request )
00091     SOL4_STATE_EVENT( evt_server_reply )
00092   SOL4_STATE_FINISH()
00093 
00094 SOL4_CLASS_FINISH()
00095 
00096 a_cln_t::a_cln_t()
00097   :
00098     base_type_t( agent_name().c_str() )
00099 {
00100   // Делаем агента активным объектом.
00101   so_add_traits( so_4::disp::active_obj::
00102     query_active_obj_traits() );
00103 }
00104 
00105 a_cln_t::~a_cln_t()
00106 {
00107 }
00108 
00109 void
00110 a_cln_t::so_on_subscription()
00111 {
00112   // Подписываем те события, инциденты для которых
00113   // в системе уже существуют.
00114 
00115   so_subscribe( "evt_start",
00116     so_4::rt::sobjectizer_agent_name(), "msg_start" );
00117 
00118   so_subscribe( "evt_send_request", "msg_send_request" );
00119 }
00120 
00121 const std::string &
00122 a_cln_t::agent_name()
00123 {
00124   static std::string name( "a_cln_t" );
00125   return name;
00126 }
00127 
00128 void
00129 a_cln_t::evt_start()
00130 {
00131   // Агент стартовал.
00132 
00133   // Нужно зарегистрировать глобального агента и
00134   // подписаться на его сообщение.
00135   so_4::ret_code_t rc = so_4::api::make_global_agent(
00136     c1i_t::agent_name(),
00137     c1i_t::agent_type() );
00138   if( rc )
00139     std::cerr << rc << std::endl;
00140   else
00141     so_subscribe( "evt_server_reply",
00142       c1i_t::agent_name(), "msg_reply" );
00143 }
00144 
00145 void
00146 a_cln_t::evt_send_request(
00147   const msg_send_request * )
00148 {
00149   so_4::api::send_msg( c1i_t::agent_name(),
00150     "msg_request", 0 );
00151 }
00152 
00153 void
00154 a_cln_t::evt_server_reply(
00155   const c1i_t::msg_reply * )
00156 {
00157   // Ответ сервера получен.
00158   std::cout << "Reply from server received" << std::endl;
00159 }
00160 
00161 // Создание кооперации, в которую входит главный агент
00162 // клиента #1 и коммуникационный агент (клиентский сокет).
00163 void
00164 create_coop(
00165   // Адрес серверного сокета.
00166   const char * sock_addr )
00167 {
00168   a_cln_t * a_cln = new a_cln_t();
00169 
00170   // Создание клиентского сокета для взаимодействия по SOP.
00171   // Фильтр, который допускает только сообщения агента c1i.
00172   so_4::sop::std_filter_t * filter =
00173     so_4::sop::create_std_filter();
00174   filter->insert( c1i_t::agent_name() );
00175 
00176   so_4::rt::comm::a_cln_channel_t * a_sock =
00177     new so_4::rt::comm::a_cln_channel_t(
00178       "a_sock",
00179       so_4::socket::channels::create_client_factory( sock_addr ),
00180       // Назначаем фильтр.
00181       filter,
00182       // Назначаем обработчик разрывов связи.
00183       so_4::rt::comm::a_cln_channel_base_t::create_def_disconnect_handler(
00184         5000, 0 )
00185     );
00186   // Сокет так же будет активным агентом.
00187   so_4::disp::active_obj::make_active( *a_sock );
00188   // Поскольку трафик предполагается небольшой, то устанавливаем
00189   // порог так, чтобы сообщения уходили сразу же.
00190   a_sock->set_out_threshold( so_4::rt::comm::threshold_t( 1, 1 ) );
00191 
00192   so_4::rt::agent_t * agents[] =
00193   {
00194     a_cln, a_sock
00195   };
00196   so_4::rt::dyn_agent_coop_helper_t coop_helper(
00197     new so_4::rt::dyn_agent_coop_t(
00198       "client_coop", agents,
00199       sizeof( agents ) / sizeof( agents[ 0 ] ) ) );
00200 
00201   if( coop_helper.result() )
00202     std::cerr << "register_coop:\n"
00203       << coop_helper.result() << std::endl;
00204 }
00205 
00206 // Уничтожение клиентской кооперации.
00207 void
00208 destroy_coop()
00209 {
00210   so_4::ret_code_t rc =
00211     so_4::api::deregister_coop( "client_coop" );
00212   if( rc )
00213     std::cerr << "deregister_coop:\n" << rc << std::endl;
00214 }
00215 
00216 //
00217 // Нить, на которой будет происходить запуск SObjectizer-а
00218 //
00219 class sobj_thread_t :
00220   public threads_1::thread_t
00221 {
00222   public :
00223     sobj_thread_t();
00224     virtual ~sobj_thread_t();
00225 
00226   protected :
00227     virtual void
00228     body();
00229 };
00230 
00231 sobj_thread_t::sobj_thread_t()
00232 {
00233 }
00234 
00235 sobj_thread_t::~sobj_thread_t()
00236 {
00237 }
00238 
00239 void
00240 sobj_thread_t::body()
00241 {
00242   std::auto_ptr< so_4::timer_thread::timer_thread_t >
00243     timer_ptr( so_4::timer_thread::simple::create_timer_thread() );
00244 
00245   std::auto_ptr< so_4::rt::dispatcher_t >
00246     disp_ptr( so_4::disp::active_obj::create_disp( *timer_ptr ) );
00247 
00248   so_4::ret_code_t rc = so_4::api::start( *disp_ptr, 0 );
00249   if( rc )
00250   {
00251     std::cerr << "start: " << rc << std::endl;
00252   }
00253 }
00254 
00255 int
00256 main( int argc, char ** argv )
00257 {
00258   if( 2 == argc )
00259   {
00260     sobj_thread_t thread;
00261     thread.start();
00262 
00263     // Засыпаем, чтобы дать стартовать SObjectizer.
00264     // Это самый простой способ синхронизации с sobj_thread_t.
00265     threads_1::sleep_thread( 1000 );
00266 
00267     bool is_continue = true;
00268     while( is_continue )
00269     {
00270       std::string choice;
00271 
00272       std::cout << "Choose action:\n"
00273         "\t0 - quit\n"
00274         "\t1 - create client coop\n"
00275         "\t2 - destroy client coop\n"
00276         "\t3 - send request to server\n> "
00277         << std::flush;
00278 
00279       std::cin >> choice;
00280 
00281       if( choice == "0" )
00282       {
00283         // Завершаем работу.
00284         so_4::api::send_msg(
00285           so_4::rt::sobjectizer_agent_name(),
00286           "msg_normal_shutdown", 0,
00287           so_4::rt::sobjectizer_agent_name() );
00288         is_continue = false;
00289       }
00290       else if( choice == "1" )
00291         // Создаем кооперацию клиента.
00292         create_coop( argv[ 1 ] );
00293       else if( choice == "2" )
00294         // Уничтожаем кооперацию клиента.
00295         destroy_coop();
00296       else if( choice == "3" )
00297       {
00298         // Отсылаем запрос серверу.
00299         so_4::api::send_msg(
00300           a_cln_t::agent_name(),
00301           "msg_send_request", 0 );
00302       }
00303     }
00304 
00305     // Ожидаем завершения SObjectizer.
00306     thread.wait();
00307 
00308     return 0;
00309   }
00310   else
00311   {
00312     std::cerr << "sample_filter_c1 <server_sock_addr>"
00313       << std::endl;
00314 
00315     return -1;
00316   }
00317 }

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