sample/raw_channel/tcp_cln.cpp

00001 /*
00002   Пример, демонстрирующий работу с серверным raw-соединением.
00003 
00004   Производится попытка подключения к указанному адресу,
00005   после чего в соединение отсылаются все необязательные
00006   аргументы командной строки. После этого осуществляется
00007   переход в режим чтения и отображения данных.
00008 */
00009 
00010 #include <iostream>
00011 
00012 // Базовые заголовочные файлы SObjectizer.
00013 #include <so_4/rt/h/rt.hpp>
00014 #include <so_4/api/h/api.hpp>
00015 
00016 #include <so_4/timer_thread/simple/h/pub.hpp>
00017 #include <so_4/disp/active_obj/h/pub.hpp>
00018 
00019 // Описание агента, который обслуживает серверный
00020 // raw-канал и средств для создания каналов.
00021 #include <so_4/rt/comm/h/a_raw_cln_channel.hpp>
00022 #include <so_4/socket/channels/h/channels.hpp>
00023 
00024 //
00025 // Класс агента, который будет работать с серверным соединением.
00026 //
00027 class a_main_t :
00028   public so_4::rt::agent_t
00029 {
00030   typedef so_4::rt::agent_t base_type_t;
00031 
00032   public :
00033     a_main_t(
00034       int argc,
00035       char ** argv );
00036     virtual ~a_main_t();
00037 
00038     virtual const char *
00039     so_query_type() const;
00040 
00041     virtual void
00042     so_on_subscription();
00043 
00044     // Имя главного тестового агента, который должен
00045     // присутствовать в приложении в единственном числе.
00046     static std::string &
00047     agent_name();
00048 
00049     // Имя агента клиентского соединения, который должен
00050     // присутствовать в приложении в единственном числе.
00051     static std::string &
00052     tcp_agent_name();
00053 
00054     // Реакция на успешное создание клиентского сокета.
00055     void
00056     evt_success(
00057       const so_4::rt::comm::a_cln_channel_base_t::msg_success * );
00058 
00059     // Реакция на неудачное создание клиентского сокета.
00060     void
00061     evt_fail(
00062       const so_4::rt::comm::a_cln_channel_base_t::msg_fail * );
00063 
00064     // Реакция на подключение клиента.
00065     void
00066     evt_client_connected(
00067       const so_4::rt::comm::msg_client_connected * cmd );
00068 
00069     // Реакция на отключение клиента.
00070     void
00071     evt_client_disconnected(
00072       const so_4::rt::comm::msg_client_disconnected * cmd );
00073 
00074     // Реакция на поступление данных в канал.
00075     void
00076     evt_incoming_data(
00077       const so_4::rt::comm::msg_raw_package * cmd );
00078 
00079   private :
00080     char ** m_argv;
00081     int m_argc;
00082 
00083     // Завершение работы примера.
00084     void
00085     shutdown()
00086     {
00087       so_4::api::send_msg(
00088         so_4::rt::sobjectizer_agent_name(),
00089         "msg_normal_shutdown", 0 );
00090     }
00091 };
00092 
00093 SOL4_CLASS_START( a_main_t )
00094 
00095   SOL4_EVENT_STC(
00096     evt_success,
00097     so_4::rt::comm::a_cln_channel_base_t::msg_success )
00098   SOL4_EVENT_STC(
00099     evt_fail,
00100     so_4::rt::comm::a_cln_channel_base_t::msg_fail )
00101   SOL4_EVENT_STC(
00102     evt_client_connected,
00103     so_4::rt::comm::msg_client_connected )
00104   SOL4_EVENT_STC(
00105     evt_client_disconnected,
00106     so_4::rt::comm::msg_client_disconnected )
00107   SOL4_EVENT_STC(
00108     evt_incoming_data,
00109     so_4::rt::comm::msg_raw_package )
00110 
00111   SOL4_STATE_START( st_normal )
00112     SOL4_STATE_EVENT( evt_success )
00113     SOL4_STATE_EVENT( evt_fail )
00114     SOL4_STATE_EVENT( evt_client_connected )
00115     SOL4_STATE_EVENT( evt_client_disconnected )
00116     SOL4_STATE_EVENT( evt_incoming_data )
00117   SOL4_STATE_FINISH()
00118 
00119 SOL4_CLASS_FINISH()
00120 
00121 a_main_t::a_main_t(
00122   int argc,
00123   char ** argv )
00124 :
00125   base_type_t( agent_name().c_str() )
00126 , m_argc( argc )
00127 , m_argv( argv )
00128 {
00129 }
00130 
00131 a_main_t::~a_main_t()
00132 {
00133 }
00134 
00135 void
00136 a_main_t::so_on_subscription()
00137 {
00138   so_subscribe( "evt_success", tcp_agent_name(), "msg_success" );
00139 
00140   so_subscribe( "evt_fail", tcp_agent_name(), "msg_fail" );
00141 
00142   so_subscribe( "evt_client_connected", tcp_agent_name(),
00143     "msg_client_connected" );
00144 
00145   so_subscribe( "evt_client_disconnected", tcp_agent_name(),
00146     "msg_client_disconnected" );
00147 
00148   so_subscribe( "evt_incoming_data", tcp_agent_name(),
00149     "msg_raw_package" );
00150 }
00151 
00152 std::string &
00153 a_main_t::agent_name()
00154 {
00155   static std::string name( "a_main" );
00156 
00157   return name;
00158 }
00159 
00160 std::string &
00161 a_main_t::tcp_agent_name()
00162 {
00163   static std::string name( "a_tcp_srvsock" );
00164 
00165   return name;
00166 }
00167 
00168 void
00169 a_main_t::evt_success(
00170   const so_4::rt::comm::a_cln_channel_base_t::msg_success * )
00171 {
00172   std::cout << so_query_name() << ".evt_success" << std::endl;
00173 }
00174 
00175 void
00176 a_main_t::evt_fail(
00177   const so_4::rt::comm::a_cln_channel_base_t::msg_fail * cmd )
00178 {
00179   std::cout << so_query_name() << ".evt_fail: "
00180     << cmd->m_ret_code << std::endl;
00181 
00182   shutdown();
00183 }
00184 
00185 // Замена последовательности "\n" на \r\n.
00186 const std::string &
00187 replace_escaped_lf( std::string & what )
00188 {
00189   std::string::size_type where = 0;
00190   while( std::string::npos != ( where = what.find( "\\n", where ) ) )
00191   {
00192     what.replace( where, 2, "\r\n" );
00193     where += 2;
00194   }
00195 
00196   return what;
00197 }
00198 
00199 void
00200 a_main_t::evt_client_connected(
00201   const so_4::rt::comm::msg_client_connected * cmd )
00202 {
00203   std::cout << so_query_name() << ".evt_client_connected: "
00204     << cmd->m_channel.comm_agent() << ", "
00205     << cmd->m_channel.client()
00206     << std::endl;
00207 
00208   // Нужно отсылать данные в соединение.
00209   std::cout << "sending data" << std::endl;
00210   for( int i = 0; i != m_argc; ++i )
00211   {
00212     std::string what( m_argv[ i ] );
00213     replace_escaped_lf( what );
00214 
00215     // Данные нужно подготовить в comm_buf.
00216     so_4::rt::comm_buf_t data;
00217     data.insert( 0, what.data(), what.size() );
00218     data.insert( data.size(), "\r\n\r\n", 4 );
00219 
00220     // Отсылаем данные.
00221     so_4::api::send_msg_safely(
00222       cmd->m_channel.comm_agent(), "msg_send_package",
00223       new so_4::rt::comm::msg_send_package(
00224         cmd->m_channel.client(),
00225         data ) );
00226   }
00227 }
00228 
00229 void
00230 a_main_t::evt_client_disconnected(
00231   const so_4::rt::comm::msg_client_disconnected * cmd )
00232 {
00233   std::cout << so_query_name() << ".evt_client_disconnected: "
00234     << cmd->m_channel.comm_agent() << ", "
00235     << cmd->m_channel.client()
00236     << std::endl;
00237 
00238   shutdown();
00239 }
00240 
00241 void
00242 a_main_t::evt_incoming_data(
00243   const so_4::rt::comm::msg_raw_package * cmd )
00244 {
00245   std::cout << so_query_name() << ".evt_incoming_data: "
00246     << cmd->m_channel.comm_agent() << ", "
00247     << cmd->m_channel.client()
00248     << "\n\tdata size: " << cmd->m_package.size()
00249     << "\n\tis channel blocked: " << cmd->m_is_blocked
00250     << std::endl;
00251 
00252   std::string v(
00253     (const char *)cmd->m_package.ptr(),
00254     cmd->m_package.size() );
00255   std::cout << v << std::endl;
00256 
00257   // Если канал оказался заблокированным, то разблокируем его.
00258   cmd->unblock_channel();
00259 }
00260 
00261 // Создание главной кооперации примера.
00262 so_4::rt::agent_coop_t *
00263 create_coop( const char * ip_address,
00264   int argc,
00265   char ** argv )
00266 {
00267   a_main_t * a_main = new a_main_t( argc, argv );
00268   so_4::rt::comm::a_raw_cln_channel_t * a_tcp_clnsock =
00269     new so_4::rt::comm::a_raw_cln_channel_t(
00270       a_main_t::tcp_agent_name(),
00271       so_4::socket::channels::
00272         create_client_factory( ip_address ) );
00273   // Сокет должен быть активным объектом.
00274   a_tcp_clnsock->so_add_traits(
00275     so_4::disp::active_obj::query_active_obj_traits() );
00276   // Чтение следуюшего буфера должно осуществляться только,
00277   // если мы успели обработать предыдущий пакет.
00278   a_tcp_clnsock->set_in_threshold(
00279     so_4::rt::comm::threshold_t( 1, 1 ) );
00280   // Запись должна осуществляться для каждого исходящего пакета.
00281   a_tcp_clnsock->set_out_threshold(
00282     so_4::rt::comm::threshold_t( 1, 1 ) );
00283 
00284   so_4::rt::agent_t * agents[] = {
00285     a_main, a_tcp_clnsock
00286   };
00287 
00288   return new so_4::rt::dyn_agent_coop_t( "srvsock1",
00289       agents, sizeof( agents ) / sizeof( agents[ 0 ] ) );
00290 }
00291 
00292 int
00293 main( int argc, char ** argv )
00294 {
00295   if( 2 <= argc )
00296   {
00297     // Создаем таймер, диспетчер. Затем запускаем
00298     // run-time SObjectizer-а.
00299     so_4::ret_code_t rc = so_4::api::start(
00300       // Диспетчер будет уничтожен при выходе из start().
00301       so_4::disp::active_obj::create_disp(
00302         // Таймер будет уничтожен диспетчером.
00303         so_4::timer_thread::simple::create_timer_thread(),
00304         so_4::auto_destroy_timer ),
00305       so_4::auto_destroy_disp,
00306       create_coop( argv[ 1 ], argc - 2, &(argv[ 2 ]) ) );
00307     if( rc )
00308     {
00309       // Ошибка старта.
00310       std::cerr << "start: " << rc << std::endl;
00311     }
00312 
00313     return rc;
00314   }
00315   else
00316     std::cerr << "sample_raw_channel_tcp_cln "
00317       "<ip-address> [data_to_send]"
00318       << std::endl;
00319 
00320   return 0;
00321 }

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