Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> удаленный вызов. детали, реализация, архитектура, у темы новое название! 
:(
    Опции темы
mes
Дата 24.11.2010, 15:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



вот заготовка примера клиент-сервер и теста для двух клиентов..
для полноты осталось реализовать методы sercer_side::session (мне уже лень... smile )
http://liveworkspace.org/code/dd7b29ae22f2...eeecc13ccd2146a

Добавлено @ 15:27
ну и для наглядности выложу тут :

connection :
Код

namespace meta {
template<class T>
struct msg_id;

template <typename T>
struct proxy;

}// namespace meta

namespace discoly {

struct connection 
{
   template <typename M>
   connection& operator << (M const& m) 
   { 
       if (auto * invoker = vtable[meta::msg_id<M>::value])
        invoker->call(&m);
        
       return *this; 
   }
  struct i_invoker { virtual void call(void const* pack) =0; };
  
  template <typename T, typename M>
  struct invoker : i_invoker
  {
    void call (void const *  pack) { 
              meta::proxy<T>  proxy; 
              proxy.o = obj; 
              proxy.fn(*static_cast<M const*>(pack)); }   
     
    invoker (T * o) : obj(o) {}
    T * obj;    
  };
  
  template <typename T> 
  void reg (T& target)
  {
      bind<T, typename meta::proxy<T>::M1>(target);
      bind<T, typename meta::proxy<T>::M2>(target);
      bind<T, typename meta::proxy<T>::M3>(target);
  }
  
  template <typename T, typename M> 
  void bind (T& target)
  {
      vtable[meta::msg_id<M>::value] = new invoker<T,M>(&target);
  }
  
  connection():vtable({0}) {}
  i_invoker *  vtable [100];
};  

} // namespace discoly



сообщения протокола
Код


namespace msg {
namespace cts {

   struct user    { std::string nick; };
   struct quit    {};
   struct talkmsg { std::string to, phrase; };   
     
} // namespace cts

namespace stc {

   struct ident_ok  { std::string nick; };
   struct ident_no  { std::string reason; };
   struct talkmsg   { std::string from, phrase; };
   
   struct err_no_such_user {};   
   
} // namespace stc
} // namespace msg


определение ид для сообщений протокола
Код


namespace meta {

template <>
struct msg_id<msg::cts::user>     { enum { value = 0 }; };
template <>
struct msg_id<msg::cts::quit>     { enum { value = 1 }; };
template <>
struct msg_id<msg::cts::talkmsg> { enum { value = 4 }; };

template <>
struct msg_id<msg::stc::ident_ok> { enum { value = 10 }; };
template <>
struct msg_id<msg::stc::ident_no> { enum { value = 11 }; };
template <>
struct msg_id<msg::stc::talkmsg>  { enum { value =  12 }; };
template <>
struct msg_id<msg::stc::err_no_such_user>  { enum { value =  20 }; };

} // namespace meta


обработчики сервера
Код

using discoly::connection;

namespace server_side {

struct user;

struct session
{    
   bool add_user    (user&) {  return true; }
   bool remove_user (user&) {  return true; }   

   user * get_user (std::string const& nick) 
   {
     return NULL;
   }
};

struct user
{
 
   user (connection& tie
        ,session& ses) 
     : _tie(tie) 
     , _ses(ses)
     , _nick("")
   {
      _tie.reg(*this);
   }
   void handle (msg::cts::user const& m)
   {
      
      if (_ses.get_user(m.nick))      
      {
         _tie<<msg::stc::ident_no();  
      }             
      else 
      {      
         _nick = m.nick;   
         _ses.add_user(*this);

         _tie<<msg::stc::ident_ok({_nick});                
      }
       
   }
   void handle (msg::cts::quit const& )
   {
       _ses.remove_user (*this);

       _tie<<msg::stc::ident_no({"quit"});
   }
   void handle (msg::cts::talkmsg const& m)
   {      
     if (auto usr = _ses.get_user (m.to) )
     {
        usr->talkmsg(*this, m.phrase);            
     }
     else
     {
        _tie<<msg::stc::err_no_such_user();     
     }
   }

   void talkmsg (user& usr, std::string const& phrase )
   {
       _tie<<msg::stc::talkmsg ({ usr._nick, phrase });  
   }
   
      
 private:
   connection   &_tie;
   session      &_ses;
   std::string   _nick;
};



struct server 
{    
  connection& connect () 
  {
    auto * tie  = new connection();
    new user (*tie, _ses);  
     
    return *tie;
  }
  session _ses;
  
};

} //namespace server_side
using server_side::server;

прокси для server_side::user
Код


namespace meta {
template<>
struct proxy<server_side::user>
{
  typedef void a;
  server_side::user * o;
  
  typedef msg::cts::user M1;
  typedef msg::cts::quit M2;
  typedef msg::cts::talkmsg  M3;
  
  template <class T>
  a fn (T const& m) { o-> handle (m); }
};
} // namespace meta

клиент:
Код

mespace client_side {

struct client
{
// --
   void enter    (std::string const& nick)
   {
      _out << _id << " : ";
      _out << "try entering" << std::endl ;
      
      _tie << msg::cts::user({nick});
   }
   void quit     (std::string const& phrase)
   {
      _out << _id << " : ";   
      _out << "try quit"<< std::endl;
      
      _tie << msg::cts::quit ();
   }
   
   void talkmsg  (std::string const& to
                 ,std::string const& phrase)
   { 
      _out << _id << " : ";   
      _out <<_nick << " -> " << to << " : " << phrase << std::endl;
      
      _tie << msg::cts::talkmsg ();
   }

// --
   void on_ident_ok (std::string const& nick)   
   {
      _out << _id << " : ";   
      _out << "enter as " << nick << std::endl;
      
      _nick = nick; 
   }
   void on_ident_no (std::string const& reason) 
   {
      _out << _id << " : ";   
      _out << "quit (reason: " << reason << ")" << std::endl;
      
     _nick = "";   
   }
   void on_talkmsg (std::string const& from
                   ,std::string const& phrase) 
   {
      _out << _id << " : ";   
      _out << _nick << " <- " << from << " : " << phrase << std::endl;        
   }
// --
   std::string get_nick() const { return _nick; }

// --
   client (connection & tie
          ,std::ostream& os
          ,std::string const& id) 
          
     : _tie(tie)
     , _out(os)
     , _id (id)
     , _nick("") 
   {      
      _tie.reg (*this);
   }

 private:
   connection         &_tie;
   std::ostream       &_out;
   std::string         _id;
   std::string         _nick;     
};

} // namespace client_side;
using client_side::client;

прокси для клиента:
Код


namespace meta {
template<>
struct proxy<client_side::client>
{
  typedef void a;
  client_side::client * o;
  
  typedef msg::stc::ident_ok M1;
  typedef msg::stc::ident_no M2;
  typedef msg::stc::talkmsg  M3;
  
  a fn (msg::stc::ident_ok const& m) { o-> on_ident_ok(m.nick); }
  a fn (msg::stc::ident_no const& m) { o-> on_ident_no(m.reason); }
  a fn (msg::stc::talkmsg  const& m) { o-> on_talkmsg (m.from, m.phrase); }   
};
}

тест:
Код


int main ()
{
   server _srvr;
  
   client c1 (_srvr.connect(), std::cout, "one");
   client c2 (_srvr.connect(), std::cout, "two");
   
   
   c1.enter ("any");  
   c2.enter ("other");
   
   c1.talkmsg ("other", "hallo");
   c2.talkmsg ("any", "hallo, how are you?");

   c1.quit ("good-bye");
   c2.quit ("bye-bye");
}


вывод теста:
Цитата

one : try entering
one : enter as any
two : try entering
two : enter as other
one : any -> other : hallo
two : other -> any : hallo, how are you?
one : try quit
one : quit (reason: quit)
two : try quit
two : quit (reason: quit)



обратите внимание на исполнение прокси серверной и клиентской частей.. 
в одном случае идет прямое отажение имени и требует от реализации перегруженных функций..
в другом каждое сообщение имеет имя функции обработчика..
есть еще третий вариант совмещение этих подходов.. 

Это сообщение отредактировал(а) mes - 24.11.2010, 15:32


--------------------
PM MAIL WWW   Вверх
mes
Дата 24.11.2010, 15:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



если вариант устраивает, то могу дать задания, как это улучшить  smile 


--------------------
PM MAIL WWW   Вверх
mes
Дата 24.11.2010, 18:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Вы пока разбираетесь, я начну перечислять недостатки и возможные способы решения... 

для начала у нас есть зависимость connection от
Код

namespace meta {
template<class T>
struct msg_id;
template <typename T>
struct proxy;
}// namespace meta


Добавлено @ 18:12
так как сообщения у нас делятся по группам создадим их прообразы :
Код

namespace meta {
   template <size_t N>
   struct cts_msg
   {
      // assert (N<10)
      enum { discoly_msg_id = N + 0 };     
   };

   template <size_t N>
   struct cts_msg
   {
      // assert (N<10)
      enum { discoly_msg_id = N + 10 };     
   };
}

и на их основе будем определять сообщения.. 
Код

namespace msg {
namespace cts {

   struct user : meta::cts_msg<0>  {..};
   struct quit : meta::cts_msg<1>  {..};
   ...
     
} // namespace cts

namespace stc {

   struct ident_ok : meta::stc_msg<0>  {..};
   struct ident_no : meta::stc_msg<1>  {..};
   ...      
} // namespace stc
} // namespace msg

естественно в connection внести соответствующие изменения.. 


Это сообщение отредактировал(а) mes - 24.11.2010, 18:13


--------------------
PM MAIL WWW   Вверх
mes
Дата 24.11.2010, 18:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



с агентами что то в этом стиле :

Код

struct client_proxy;

namespace meta {
struct client  {

 typedef boost::mpl::vector
  < stc::ident_ok
  , stc::ident_no
  , stc::talkmsg
  > discoly_delivery_typelist ;

  typedef client_proxy discoly_delivery;

}; 
} //  namespace meta

struct client : meta::client
{
 ..
};

struct client_proxy
{
  typedef void a;
  client * o;
  
  a fn (msg::stc::ident_ok const& m) { o-> on_ident_ok(m.nick); }
  a fn (msg::stc::ident_no const& m) { o-> on_ident_no(m.reason); }
  a fn (msg::stc::talkmsg  const& m) { o-> on_talkmsg (m.from, m.phrase); }   
};



Это сообщение отредактировал(а) mes - 24.11.2010, 19:06


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 24.11.2010, 18:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



mes, позвольте вопрос smile 
сейчас, типы proxy должны знать о том, что проксируют. но я предполагаю их генерировать, а не писать руками. по этому, возникает проблема:
http://liveworkspace.org/code/063ad5f98dc7...8aa0ce7e3b59e8a
это можно как-то решить?
PM WWW   Вверх
mes
Дата 24.11.2010, 18:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



второй шаг : добавить сериализацию пакетов и изменить передачу  (void const*) на discoly::packet const&
третий : connection сделать абстрактным, и на нем образовать tcp_connection (через асио)

Цитата(boostcoder @  24.11.2010,  17:28 Найти цитируемый пост)
т. но я предполагаю их генерировать,

для начала оставьте предположения, и давайте доведем код удобовариваемого вида..
а там уже в конце будет видно, что кодогенерить, а что не надо.. потому как фактически устоявшегося еще пока ничего нет..

Цитата(boostcoder @  24.11.2010,  17:28 Найти цитируемый пост)
это можно как-то решить? 

по задумке прокси "составляется" после описания интерфейса объекта.. 
решить можно, сделав структуру прокси шаблоной..

в первых примерах (где то две страницы назад) уже такое было..
вот: meta_invoker из http://liveworkspace.org/code/d867c7fd3a7a...d2b7a1e2b325512

Добавлено через 11 минут и 12 секунд
но, еще раз повторю: 
Цитата(mes @  24.11.2010,  17:33 Найти цитируемый пост)
для начала оставьте предположения, и давайте доведем код удобовариваемого вида..

 smile 

Это сообщение отредактировал(а) mes - 24.11.2010, 18:44


--------------------
PM MAIL WWW   Вверх
mes
Дата 24.11.2010, 19:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



и еще нужно namespace msg  пока переименовать в net..




--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 24.11.2010, 19:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



mes, а что если я Вас добавлю в список коммитеров?
сможете сами вносить изменения.

Добавлено через 1 минуту и 7 секунд
я это не от того что мне лень, или я Вас поэксплуатировать хочу. просто у меня основные времязатраты - это понимание того что Вы пишите smile 
PM WWW   Вверх
mes
Дата 24.11.2010, 19:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(boostcoder @  24.11.2010,  18:50 Найти цитируемый пост)
mes, а что если я Вас добавлю в список коммитеров?

давайте попробуем smile


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 24.11.2010, 20:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



сделал.

Это сообщение отредактировал(а) boostcoder - 24.11.2010, 20:12
PM WWW   Вверх
mes
Дата 24.11.2010, 20:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(boostcoder @  24.11.2010,  19:07 Найти цитируемый пост)
 т.к. я не уверен что гуглкод нормально отнесется к тому, что у Вас не гугл почта

отправил в личку имя гугл почты.. 



--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 24.11.2010, 20:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



проверяйте.


Это сообщение отредактировал(а) boostcoder - 24.11.2010, 20:18
PM WWW   Вверх
mes
Дата 24.11.2010, 20:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(boostcoder @  24.11.2010,  19:13 Найти цитируемый пост)
их всего две   

gоogle.svn впервые.. но в принципе как - знаю smile


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 24.11.2010, 20:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(mes @  24.11.2010,  18:33 Найти цитируемый пост)
в первых примерах (где то две страницы назад) уже такое было..
вот: meta_invoker из http://liveworkspace.org/code/d867c7fd3a7a...d2b7a1e2b325512

не понимаю как это можно адаптировать..
PM WWW   Вверх
mes
Дата 24.11.2010, 20:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(boostcoder @  24.11.2010,  19:37 Найти цитируемый пост)
не понимаю как это можно адаптировать.. 

адаптировать под что ?


--------------------
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0752 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.