Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > реализации RPC на С++


Автор: GoldFinch 8.8.2009, 21:04
какие есть реализации RPC (remote procedure call) на С++ 
удобные в плане расширения-переделки, написания пользовательского кода?

какие вообще есть подходы к реализации RPC на С++ ?

Автор: GoldFinch 8.8.2009, 21:23
интересны только библиотеки с открытым исходным кодом, чтобы можно было допилить под конкретную задачу, а не COM и т.п.

Автор: Cheloveck 8.8.2009, 23:48
http://ru.wikipedia.org/wiki/CORBA

Автор: Любитель 9.8.2009, 07:08
Для обычного SOAP можно найти библиотечки.

Автор: azesmcar 9.8.2009, 08:09
http://libiqxmlrpc.wikidot.com/
http://ulxmlrpcpp.sourceforge.net/
http://xmlrpc-c.sourceforge.net/
http://xmlrpcpp.sourceforge.net/
http://sourceforge.net/projects/xmlrpcc4win/

Автор: GoldFinch 9.8.2009, 11:47
омг почему они все такие неудобные?
мне надо взять готовую систему, и поделить на 2 части, связав их RPC, при этом процесс разделения должен вносить минимальные изменения в код системы, 
например было
Код

//foo.h
void foo(int a, int b)
{
... // реализация
}

//user_code.cpp
foo(1,2);

а стало
Код

//foo.h
void foo(int a, int b)
{
    Archive archive;
    archive<<FOO_ID<<a<<b;
    send(archive);
}

//user_code.cpp
foo(1,2);

но писать на каждую функцию\метод по заглушке я не хочу, а хочу чтобы они както генерились библиотекой RPC

транспорт (сетевой протокол) мне нужен свой, он у меня есть, своя сериализация у меня тоже есть
проблема только в самом RPC, как его получше сделать

например возможен такой код
Код

//rpc.h
#define RPC_DECL(id,name) \
    {    rpc::remote::call(id,_AddressOfReturnAddress(),&name); }

namespace rpc {
    namespace remote {
                template<typename T1, typename T2>
        void call( rpc_id_t id, void* frame, void(*)(T1,T2) )
        {
#pragma pack(push,4)
            struct StackFrame
            {
                char* retaddr;
                T1 a1;
                T2 a2;
            } *f = (StackFrame*)frame;
#pragma pack(pop)
            network::packetbuf buf;
            serialization::raw_oarchive<network::packetbuf> ar(buf);
            ar<< id << f->a1 << f->a2;
            conn_.send(buf);
        }

//foo.h
void foo(int a, int b)
     RPC_DECL( FOO_ID, foo )

//user_code.cpp
foo(1,2);


а всякие реализации CORBA, XML-RPC со своими транспортами и необходимостью писать МНОГО кода - мне не нужны
даже в статье http://www.rsdn.ru/article/files/libs/RPCLib.xml более удобное решение, правда с дефайнами

Автор: Любитель 9.8.2009, 12:50
Если ты хочешь использовать собственный протокол - то зачем нужна библиотека?! Сделать обёртку для вызова метода - вообщем-то можно. Автоматически подставить везде вызов обёртки невозможно само собой. Должен быть способ опознавания ремоут-метода от не-ремоут. Удобный вариант - если у тебя все ремоут-методы через интерфейсы вызываются и создаются через фабрику. Тогда можно написать генератор реализаций обёрток (и самой фабрики) и использовать полученный код.

Автор: mes 9.8.2009, 13:23
Цитата(GoldFinch @  9.8.2009,  10:47 Найти цитируемый пост)
но писать на каждую функцию\метод по заглушке я не хочу, а хочу чтобы они както генерились библиотекой RPC

а вот такого типа заглушка устроит ?
Код

void f (int a, int b) { rpc_call ( 8, a, b ); }


ее можно например так замакросить :
Код

#define DEF_RPC_CALL_2(name, id, P1,P2) void name(P1 p1, P2 p2) { rpc_call (id,p1,p2); }

тогда :
Код

DEF_RPC_CALL_2 (f, 8, int, int)

f( 3, 5 );

Автор: GoldFinch 9.8.2009, 15:11
mes, допустим заглушка выглядит так.

разница между 
  DEF_RPC_CALL_2 (f, 8, int, int)
и 
  void f(int a, int b) DEF_RPC_CALL(8, f)
не слишком велика

-----------------------

Пока у меня получается что у клиента есть допустим такой код
Код

//Bar.h

class Bar
{
public:    
    typedef int rpc_id_t;
    typedef Bar this_t;

public:
    void ready()        { rpc::remote::call( 200 ,this,_AddressOfReturnAddress(),&this_t::ready ); } 
    void result(int r)    { rpc::remote::call( 201 ,this,_AddressOfReturnAddress(),&this_t::result ); }

public:
    Bar(network::connection& conn) : conn_(conn) {}

public:
    network::connection& conn_;
};

а у сервера такой
Код

//Bar.h

class Bar
{
public:    
    typedef int rpc_id_t;
    typedef Bar this_t;

public:
    void ready();
    void result(int r);

public:
    Bar(Foo* foo);

private:
    Foo* foo_;

public:    
    template<typename Archive>
    void Dispatch(rpc_id_t id,Archive ar)
    {
        switch(id)
        {
        case 200:    return rpc::local::call(this,&this_t::ready,ar); //определяет тип аргументов по типу &this_t::ready
        case 201:    return rpc::local::call(this,&this_t::result,ar);
        }
        assert(0 && "invalid id");
    }
};

//.cpp
Bar::Bar( Foo* foo ) : foo_(foo) { ... }
void Bar::ready() {...}
void Bar::result( int r ) {...}


хотелось бы привести оба заголовка к общему виду, и спрятать строки которые можно спрятать

Автор: GoldFinch 9.8.2009, 15:35
upd: вместо
Код

class Bar
{
public:    
    typedef int rpc_id_t;
    typedef Bar this_t;

можно написать
class Bar : public rpc_cfg<Bar>

Автор: GoldFinch 9.8.2009, 16:14
upd2

template<typename Archive> 
void Bar::Dispatch(rpc_id_t id,Archive ar)

можно вынести из класса в отдельную функцию

template<typename idT, typename Archive>
void Dispatch(Bar* that, idT id, Archive ar)

тогда от .h файлов останется только

Код

class Bar : public rpc_remote_cfg<Bar>
{
public:
    void ready()        RPC_REMOTE_DECL( 200, ready )
    void result(int r)    RPC_REMOTE_DECL( 201, result )
};

и
Код

class Bar : public rpc_local_cfg<Bar>
{
public:
    void ready();
    void result(int r);

    Bar(Foo* foo);

private:
    Foo* foo_;
};

Автор: mes 9.8.2009, 17:54
Цитата(GoldFinch @  9.8.2009,  14:11 Найти цитируемый пост)

разница между 
  DEF_RPC_CALL_2 (f, 8, int, int)
и 
  void f(int a, int b) DEF_RPC_CALL(8, f)
не слишком велика

разница в неиспользовании  AddressOfReturnAddress() и в отсутствии повторного дублирования имени функции.

Автор: GoldFinch 9.8.2009, 18:07
mes, и еще во внешнем виде объявления, и необходимости подсчета числа параметров
аналог _AddressOfReturnAddress() есть и в gcc, так что это небольшое зло

Автор: GoldFinch 9.8.2009, 20:11
Цитата(Любитель @  9.8.2009,  13:50 Найти цитируемый пост)
Если ты хочешь использовать собственный протокол - то зачем нужна библиотека?!

чтобы был пример, вдруг я упустил какой-нибудь хорошой способ реализации
так например глядя на буст.сериализацию, я написал свою сериализацию
без аналога писать сложнее.

Автор: GoldFinch 10.8.2009, 14:24
неужели это такой 0day что нигде никаких аналогов нет %)

Автор: andrew_121 16.1.2010, 01:39
Цитата(GoldFinch @  9.8.2009,  11:47 Найти цитируемый пост)
мне надо взять готовую систему, и поделить на 2 части, связав их RPC, при этом процесс разделения должен вносить минимальные изменения в код системы

тот же вопрос.
ты на чем остановился?

Автор: GoldFinch 16.1.2010, 13:55
andrew_121, на том что для моей задачи проще обойтись без RPC, чем писать свое RPC

Автор: andrew_121 16.1.2010, 14:47
andrew_121, значит ты так и не решил вопрос?

Автор: GoldFinch 16.1.2010, 18:56
Цитата(andrew_121 @  16.1.2010,  14:47 Найти цитируемый пост)
andrew_121, значит ты так и не решил вопрос? 

;)

не, решил что мне не нужен этот вопрос
на С++ это слишком неудобно делать, синтаксис у него плохой и интроспекции нету

Добавлено через 1 минуту и 47 секунд
разве что писать кодогенератор который будет парсить .h c интерфейсами файлов и генерить для них код для RPC
а средствами самого С++ слишком неудобно

Автор: andrew_121 16.1.2010, 19:52
понятно. спасибо.

Автор: Любитель 16.1.2010, 21:32
Цитата(GoldFinch @  16.1.2010,  18:56 Найти цитируемый пост)
разве что писать кодогенератор который будет парсить .h c интерфейсами файлов и генерить для них код для RPC

Ну да, это типичное решение. QtDBus, скажем, так и работает. Просто генератор (moc) написан давно и.. не только для этого.

Автор: jonie 17.1.2010, 01:11
gSOAP... конечно, не похож на RPC, но удобен.

Автор: andrew_121 22.1.2010, 06:41
мдя.. велоизобретательство ни к чему не привело smile
нашел прекрасную реализацию RPC:
проект - http://www.codeproject.com/KB/threads/Rcf_Ipc_For_Cpp.aspx
доки - http://deltavsoft.com/RcfUserGuide/

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)