sample/filter/server.cpp

/*
  Сервер.

  Получает запросы от клиента #1 и передает их клиенту #2.
  Получает ответы от клиента #2 и передает их клиенту #1.
*/

#include <iostream>
#include <memory>

#include <ace/OS_main.h>

#include <so_4/rt/h/rt.hpp>
#include <so_4/rt/h/msg_auto_ptr.hpp>

#include <so_4/rt/comm/h/a_sop_incoming_channel_processor.hpp>

#include <so_4/api/h/api.hpp>

#include <so_4/timer_thread/simple/h/pub.hpp>
#include <so_4/disp/active_obj/h/pub.hpp>

#include <so_4/sop/h/filter.hpp>

#include <so_4/transport_layer/socket/h/pub.hpp>

#include "c1i.hpp"
#include "c2i.hpp"
#include "date_time_formatter.hpp"

//
// Класс главного агента серверной части.
//
class a_srv_t :
  public so_4::rt::agent_t
{
  typedef so_4::rt::agent_t base_type_t;
  public :
    a_srv_t();
    virtual ~a_srv_t();

    virtual const char *
    so_query_type() const;

    virtual void
    so_on_subscription();

    // Имя единственного агента этого типа в приложении.
    static const std::string &
    agent_name();

    // Реакция на появление агента в системе.
    void
    evt_start();

    // Реакция на запрос клиента #1.
    void
    evt_c1_request(
      const c1i_t::msg_request * );

    // Реакция на ответ клиента #2.
    void
    evt_c2_reply(
      const c2i_t::msg_reply * );
};

SOL4_CLASS_START( a_srv_t )

  SOL4_EVENT( evt_start )

  SOL4_EVENT_STC(
    evt_c1_request,
    c1i_t::msg_request )

  SOL4_EVENT_STC(
    evt_c2_reply,
    c2i_t::msg_reply )

  SOL4_STATE_START( st_normal )
    SOL4_STATE_EVENT( evt_start )
    SOL4_STATE_EVENT( evt_c1_request )
    SOL4_STATE_EVENT( evt_c2_reply )
  SOL4_STATE_FINISH()

SOL4_CLASS_FINISH()

a_srv_t::a_srv_t()
  :
    base_type_t( agent_name() )
{
}

a_srv_t::~a_srv_t()
{
}

void
a_srv_t::so_on_subscription()
{
  // Подписываем те события, инциденты для которых
  // в системе уже существуют.
  so_subscribe( "evt_start",
    so_4::rt::sobjectizer_agent_name(), "msg_start" );
}

const std::string &
a_srv_t::agent_name()
{
  static std::string name( "a_srv" );
  return name;
}

void
a_srv_t::evt_start()
{
  so_4::ret_code_t rc = so_4::api::make_global_agent(
    c1i_t::agent_name(),
    c1i_t::agent_type() );
  if( rc )
    std::cerr << rc << std::endl;
  else
  {
    rc = so_4::api::make_global_agent(
      c2i_t::agent_name(),
      c2i_t::agent_type() );
    if( rc )
      std::cerr << rc << std::endl;
    else
    {
      // Подписываемся на сообщения глобальных агентов.
      so_subscribe( "evt_c1_request",
        c1i_t::agent_name(), "msg_request" );

      so_subscribe( "evt_c2_reply",
        c2i_t::agent_name(), "msg_reply" );
    }
  }
}

void
a_srv_t::evt_c1_request(
  const c1i_t::msg_request * cmd )
{
  ACE_Date_Time now;
  std::cout << "Request from client #1, sent at (client): "
      << format( cmd->m_client_request_timestamp )
      << ", received at: "
      << format( now ) << std::endl;

  // Нужно отослать запрос клиенту #2.
  std::auto_ptr< c2i_t::msg_request > request( new c2i_t::msg_request(
      server_act_t(
          cmd->m_client_request_timestamp,
          now ) ) );
  so_4::api::send_msg_safely( c2i_t::agent_name(),
    "msg_request", request );
}

void
a_srv_t::evt_c2_reply(
  const c2i_t::msg_reply * cmd )
{
  ACE_Date_Time now;
  std::cout << "Reply from client #2, sent at (client): "
      << format( cmd->m_client_reply_time )
      << ", received at: " 
      << format( now ) << std::endl;

  // Нужно отослать ответ клиенту #1.
  std::auto_ptr< c1i_t::msg_reply > reply( new c1i_t::msg_reply() );
  reply->m_client_request_timestamp = cmd->m_act.m_client_timestamp;
  reply->m_server_request_timestamp = cmd->m_act.m_server_timestamp;
  reply->m_server_reply_timestamp = now;
  so_4::api::send_msg_safely( c1i_t::agent_name(), "msg_reply", reply );
}

int
main( int argc, char ** argv )
{
  if( 2 == argc )
  {
    // Готовимся запустить диспетчер.
    std::auto_ptr< so_4::timer_thread::timer_thread_t >
      timer_ptr( so_4::timer_thread::simple::create_timer_thread() );

    std::auto_ptr< so_4::rt::dispatcher_t >
      disp_ptr( so_4::disp::active_obj::create_disp( *timer_ptr ) );

    so_4::rt::comm::a_sop_incoming_channel_processor_t * a_channel =
        new so_4::rt::comm::a_sop_incoming_channel_processor_t(
            "a_channel",
            so_4::transport_layer::socket::create_acceptor_controller(
                so_4::transport_layer::socket::acceptor_params(
                    argv[ 1 ] ) ) );
    // Должен быть активным объектом.
    so_4::disp::active_obj::make_active( *a_channel );

    // Агент-сервер.
    a_srv_t * a_server = new a_srv_t();

    // Подготавливаем стартовую кооперацию, которая и будет
    // выполнять основную работу приложения.
    so_4::rt::agent_t * agents[] = {
      a_channel,
      a_server
    };
    so_4::rt::dyn_agent_coop_t * coop = new
      so_4::rt::dyn_agent_coop_t(
        "a_srv", agents,
        sizeof( agents ) / sizeof( agents[ 0 ] ) );

    // Запускаемся на работу.
    so_4::ret_code_t rc = so_4::api::start( *disp_ptr, coop );
    if( rc )
    {
      std::cerr << "start: " << rc << std::endl;
    }

    return int( rc );
  }
  else
  {
    std::cerr << "sample_filter_server <sock_addr>"
      << std::endl;

    return -1;
  }
}

Документация по SObjectizer v.4.4 'Тебуломста'. Последние изменения: Thu Sep 18 10:26:45 2008. Создано системой  doxygen1.5.6 Intervale SourceForge.net Logo