11.Usage of Remote Method Invocation

The usage of RMI in ProudNet is as followed.

11.1Making a PIDL file

In order to use Remote Method Invocation(RMI) from ProudNet, you need to create a file with extension PIDL.

PIDL file is a source file that defines messages being exchanged between hosts. When you compile this PIDL file, proxy and stub will get generated. We are going to include these proxy and stub in host program. More details on proxy and stub can be found from 4. Remote Method Invocation.

The basic format of using PIDL file is as followed.

Warning!! Do not use the value between 0 and 1300 & 60000 and 70000 as the first ID value of a message. It already used for ID parameter of ProudNet internal PIDL. If message ID is the same, exception will occur from AttachProxy and AttachStub function.

global <NameSpace> <The first ID value of message>
{
    ([Characteristic declaration]) <Function declaration> ( [in] Function parameter, ... );
}

Here are the detailed descriptions for above.

int a
std::vector<int> b
CString c

Example for PIDL file is as followed.

global LobbyC2S 5000  // Message ID starts from 5000
{
    Logon([in] CString name,[in] CString password); // ID=5001
    RequestRoomList([in] int pageNumber); // ID=5002
    Chat([in] CString name); // ID=5003
}

Reference

19.2 Communicating between programs written in other languages than C# and C++

11.2How to run PIDL Compiler

1. How to run PIDL Compiler on Linux

$sudo apt-get install mono-gmcs
$sudo apt-get install mono-runtime
$sudo yum install mono-devel
$sudo yum install mono-complete
$pwd 
/home/ProudNet/util
$mono PIDL.exe ../Sample/Simple/Common/*.pidl -outdir ./

How to run PIDL Compiler on Windows

• Setup PIDL Custom Build on Visual Studio Project

그림 11-1PIDL file custom build

The details of build setting are as followed.

- Command line: <Path where holding PIDL.exe>\PIDL.exe "%(FullPath)" -outdir .\

- Description: Compiling %(Filename).pidl ...

- Output: %(RootDir)%(Directory)\%(Filename)_common.cpp;%(RootDir)%(Directory)\%(Filename)_common.h;%(RootDir)%(Directory)\%(Filename)_proxy.cpp;%(RootDir)%(Directory)\%(Filename)_proxy.h;%(RootDir)%(Directory)\%(Filename)_stub.cpp;%(RootDir)%(Directory)\%(Filename)_stub.h;%(Outputs)

- Additional dependency: <Path where holding PIDL.exe>\PIDL.exe

There are few things you need to be aware of.

When you are done with settings, try to compile PIDL file. You are supposed to get the following messages if the compile is succeeded.

1>------ Build begin: Project: ..., Configuration: Release Win32 ------
1>Compiling TestC2C.pidl ...
1>Build log has been saved to "...".
1>ProudNetTest_2005 - Error: 0, Warning: 0
========== Build: Success 1, Fail 0, Recent 0, Skip 0 ==========

Visual Studio 2005 and 2008 version support Custom Build Rules.

If you use it, it automatically apply setting when you add PIDL files.

그림 11-2Custom Build Rules setup menu

In case of a version starting with Visual Studio 2010, Build customizations can be used.

그림 11-3Build Customizations” setting menu.

Custom Build Rules use.

You can make Custom Build Rule by using Custom Build Rules at Visual Studio 2005 and 2008.

If clicking "New Rule File..." from UI that is shown when clicking Custom Build Rules, you will be able to make a rule file.

Display Name: it is the name shown at Custom Build Rules. ex) PIDL Rule

File Name: Specify a name. ex) PIDL_Custom_Build_Rule

Directory: set the directory in which the rule file will be saved. ex) PIDL Rule

If clicking "Add Build Rule..." , you will be able to make a new rule.

그림 11-4Custom Build Rule setting

The detailed information of setting is as below.

Additional Dependencies : ..\..\..\util\PIDL.exe
Batching Separator :
Command Line : ..\..\..\util\PIDL.exe "$(InputPath)" -outdir .\
Display Name : PIDL
Execution Description : Compiling $(InputName).pidl ...
File Extensions : *.pidl
Name : PIDL Custom Build Rule
Outputs : $(InputDir)\$(InputName)_common.cpp;$(InputDir)\$(InputName)_common.h;$(InputDir)\$(InputName)_proxy.cpp;$(InputDir)\$(InputName)_proxy.h;$(InputDir)\$(InputName)_stub.cpp;$(InputDir)\$(InputName)_stub.h

Once the relevant setting is completed, PIDL Build Rule will be added as below.

그림 11-5Custom Build Rules

Check the rule file that has been newly made. And if making a file at the relevant project, you will be able to check Build Tool has been automatically selected.

customizations use.

You can make a rule file by using Custom Build Rules in case of Visual Studio 2005 and 2008.

In case of a version starting with Visual Studio 2010, you can use a rule file but UI that writes the rule file is removed.

The rule file used at Visaul Studio 2005 and 2008 is 1 file whose extension is .rules but in case of a version starting with Visaul Studio 2010, 3 files whose extensions are .props, .targets and .xml will be required. As a result of this, you cannot use .rules files made at Visual Studio 2005 and 2008.

In order to use customizations at a version starting with Visaul Studio 2010, you are allowed to select one of the following 2 ways.

In case of converting the project, .rules files will be created right after being automatically converted as .props, .targets and .xml.

Defined macro at Visual Studio 2005, 2008 and starting with Visual Studio 2010 is different. If the relevant rule is not written by a macro used at a version starting with Visaul Studio 2010, you will need to convert the macro mentioned before to the macro used at a version starting with Visaul Studio 2010 before converting or you will need to modify .props, .targets and .xml respectively.

11.3Attaching RMI proxy and stub

Class name of PIDL compiled result

Class name of proxy and stub generated through PIDL file are the classes named as Proxy and Stub of namespace designated from PIDL. For instance, if you refer to PIDL file below

global TestC2S { ... };

Proxy and stub that get generated by this code become TestC2S. Proxy and TestC2S.Stub.

PIDL file name of compiled result

First, the generated source file must be included in PIDL file. For example, if you’ve compiled TestC2S.PIDL, the name of generated Proxy module becomes TestC2S_Proxy.h. And the name of Stub module becomes TestC2S_Stub.cpp, TestC2S_Stub.h.

It is not suggested to directly attach Proxy or Stub to a project under development. Even through the compiled result of PIDL file is only a text file made of C++ language, it is still a compiled result. If you are using any source control and your compiled result is for read only then it may cause a trouble.

Thus it is better to include them by using #include.

Attaching Proxy to client and server

First, you need to generate Proxy instance of PIDL compiled result. And then, you need to register the instance to Proud.CNetClient or Proud.CNetServer.

Client and server inherit Proud.IRmiHost and Proxy can be registered through the included method, Proud.IRmiHost.AttachProxy.

Each client and server can be attached with more than two of Proxy as long as the range of message ID doesn't overwrap with each other. Let's assume there is TestA.Proxy already attached in CNetClient and you want to additionally attach TestB.Proxy. And you declared the first message ID of TestA as 2100 and TestB as 2200. If the number of RMI functions declared by TestA is 200, then the range of TestA message ID becomes 2100~2300, which overwraps with the ID of TestB. When this happens, an exception will be thrown.

Attaching Stub to client and server

If you are using C++11, check out another way described below.

C++11에서의 Stub 붙이기

The stub instance of PIDL compiled result contains RMI functions that will be run by messages sent through network as virtual function. You need to inherit this Stub class and override RMI functions.

For your convenience, PIDL Compiler (ProudNet IDL) generated macros as followed. These macros are wrapped with RMI function name and parameter.

#define DECRMI_S2C_ShowChat bool ShowChat(Proud::HostID remote,Proud::RmiContext &rmiContext,const CString &a,const int &b,const float &c)
#define DEFRMI_S2C_ShowChat(DerivedClass) bool DerivedClass::ShowChat(Proud::HostID remote,Proud::RmiContext &rmiContext,const CString &a,const int &b,const float &c)

The procedure of using these macros is followed.

Here shows how you can use them.

// PIDL file contents
global LobbyC2S 5000
{
    Foo([in] int a,[in] float b);
}

// Class that inherits Stub of LobbyC2S and operates RMI
class LobbyC2SStub:public LobbyC2S::Stub
{
    DECRMI_LobbyC2S_Foo;
};

// Creation of RMI Foo routine
DEFRMI_LobbyC2S_Foo(LobbyC2SStub)
{
    // Parameter that gets passed to here is the same parameter of LobbyC2S.Foo of PIDL.
    a++;
    b++;

    return true;
}

More detailed example on this is guided in 6.1 RMI stub 구현하기 of Part III. ProudNet Tutorial

Client and server inherit Proud.IRmiHost. Stub can be registered through the included method, Proud.IRmiHost.AttachStub.

Just like Proxy, you can attach more than two of Stub as long as their message ID doesn't overwrap with each other.

The operation method of attached Proxy and Stub

Proxy and stub attached to eigher Proud.CNetServer or Proud.CNetClient get registered to proxy list and stub list inside of Proud.CNetServer or Proud.CNetClient.

Proxy has a pointer of Proud.CNetServer or Proud.CNetClient that calls for sending method of Proud.CNetServer or Proud.CNetClient.

On the other hand, when Proud.CNetServer or Proud.CNetClient receives the message then it tosses it onto stub list. Each stub analyzes the header of received message and calls for appropriate RMI. (If there is no associated RMI, then it ignores it and passes an opportunity of analyzing to a next stub.)

When Proud.CNetServer or Proud.CNetClient is destructed, the link of proxy list and stub list contained inside get disconnected as well. When this happens, all stub linked to Proud.CNetServer or Proud.CNetClient in the past no longer calls for RMI and since every proxy also stops referring to Proud.CNetServer or Proud.CNetClient, RMI doesn't operate at all.

C++11에서의 Stub 붙이기

이 부절은 구 영어 도움말에서 번역이 안되어 있는 부절입니다. 추후 번역이 필요합니다.

C++11의 람다식을 이용하면 람다 캡처를 통해 클래스 상속 관계를 생략하는 등 더 간결한 프로그래밍이 가능합니다. 아래와 같이 Stub을 구현할 때 람다식을 사용하세요.

1. StubFunctional 인스턴스를 생성하세요.

2. StubFunctional에서 구현하고자 하는 RMI 함수를 람다식 형식으로 정의하세요. 필요시 PARAM_ 매크로를 사용하세요.

아래는 람다식으로 RMI stub을 구현하는 예입니다.

<exam.pidl>
Func1([in] int a, [in] string b);

<exam.cpp>

class Exam
{
    int x = 1;

    Exam::StubFunction examStub;

    void Main()
    {
        int y = 3;
        examStub.Func1_Function = [this, y]PARAM_Exam_Func1 {
            x+=a;
            y+=a;
            return true;
        };
    }
};

11.4Communication between hosts

In order to exchange messages between hosts in ProudNet, 4. Remote Method Invocation and 11. Usage of Remote Method Invocation must be predetermined. This section explains how you can send a message to another host with RMI.

22. Sending a message