Click here to Skip to main content
Click here to Skip to main content

RMI for C++

By , 6 Aug 2009
 

Please Note

This article is quite old now. The code samples still compile with current versions of RCF, but for up to date information, please refer to this article:

RCF - Interprocess Communication for C++

Introduction

The officially sanctioned way of making distributed function calls between C++ programs is to use CORBA, but for many applications, this is overkill. The CORBA specifications allow distributed function calls to be made between code written in any number of languages, and to make it all work, specialized tools need to be integrated into the build process, in order to translate object definitions written in CORBA's IDL to whichever native language is being used (C++, Java, etc.).

However, if we assume that the server and client are both written in the same language, let us assume C++, since it is possible to do away with these complexities. In particular, instead of elaborate definitions of interfaces and marshalling specifications, we can simply defer to C++.

Instead of separate IDL files with object interfaces, we specify the interfaces directly in C++ source code, using the preprocessor, and to marshal arguments across process boundaries, we use the native C++ serialization framework provided in the latest release of the Boost library.

A Simple Example

As an example, a simple echo server looks like this:

#include <RCF/RCF.hpp> 


RCF_BEGIN(I_Echo, "I_Echo")
  RCF_METHOD_R1(std::string, echo, const std::string &);
RCF_END(I_Echo);

class Echo
{
public:
  std::string echo(const std::string &msg) { return msg; }
};

int main()
{
  int port = 50001;
  RCF::RcfServer server(port);
  server.bind<I_Echo, Echo>();
  server.start();
  return 0;
}

And the client:

#include <RCF/RCF.hpp>


RCF_BEGIN(I_Echo, "I_Echo")
  RCF_METHOD_R1(std::string, echo, const std::string &);
RCF_END(I_Echo);

int main()
{
  std::cout << RcfClient<I_Echo>("localhost", 
                               50001).echo("my message");
  return 0;
}

The Boost.Serialization library is used to serialize parameters and return values. It handles standard types and containers automatically, and is easily extended to user defined classes. It also allows us to serialize pointers, with proper handling of polymorphic pointers and multiple pointers to single objects.

Basic Usage

There are three basic steps to using this framework:

  1. Use the RCF_xxx macros to define interfaces.
  2. Use the RcfServer class to expose objects that implement the interface.
  3. Use the RcfClient<> classes to invoke methods on the objects exposed by the server.

The interface definition macros are used as follows:

RCF_BEGIN( type, type_id )
  // ...

  RCF_METHOD_xx( return_type, name, ....):
  // ...

RCF_END( type )

type is the identifier for the interface, type_id is a string giving a runtime description of the interface. The RCF_METHOD_xx macros define the member functions, and are named according to the number of arguments and whether the return value is void or not. So, for a function func accepting two strings and returning an integer, we write:

  RCF_METHOD_R2(int, func, std::string, std::string);

and if the function has a void return type, we would instead write:

  RCF_METHOD_V2(void, func, std::string, std::string);

Dispatch IDs for each function are generated automatically; the first member function is numbered 0, the next one 1, and so on. So, the order in which the functions appear in the definition is important, unlike in CORBA, where dispatch IDs are based on the function name. The dispatch IDs are generated using templates and not any preprocessor __LINE__ trickery, so the interface does not change if blank lines are inserted. The maximum number of member functions that can appear between RCF_BEGIN() and RCF_END() is at the moment limited to 25, but this limit is arbitrary.

The purpose of the RCF_xxx macros is to define the class RcfClient<type>. This class serves as a client stub, from the user's point of view, but also has facilities that allow the framework to use it as a server stub. These macros can be used in any namespace, not just the global namespace.

Once we have defined an interface using the RCF_xxx macros, we can start a server and bind the interface to concrete objects:

{
  // create the server and tell it which port to listen on

  RCF::RcfServer server(port);

  // Interface is the identifer of the interface we're exporting,

  // Object is a type that implements that interface

    
  // one object for each client

  server.bind<Interface, Object>(); 

  // ... or one object shared by all clients

  Object object;
  server.bind<Interface>(object); 

  // tell the server to start listening for connections

  server.start();

  // ...


  // the server will shut down automatically as it goes out of scope

}

The objects are statically bound to the corresponding interface; there is no need for the object to derive from an interface class as is the case for traditional dynamic polymorphism. Instead, the compiler resolves the interface at compile time, which is not only more efficient, but also allows more flexible semantics.

The server can handle multiple simultaneous clients, even in single threaded mode, and can be stopped at any time. The lifetime of objects exposed by the server is determined by the number of current connections to the given object; once there are no more live connections to the object, a timeout is set, and when it expires, the object is deleted.

To make a client call, we instantiate the corresponding RcfClient<> template and pass the server IP and port number to the constructor. When the first remote method is called, the client then attempts to connect to the server, queries for the given object, invokes the requested member function of the remote object, and then returns the remote return value.

// define the interface

RCF_BEGIN(Interface, "Interface")
  RCF_METHOD_R2(int, add, int, int);
RCF_END(Interface);

// ...


{
  std::string ip = "localhost";
  int port = 50001;
  RcfClient<Interface> client(ip, port);
  
  // connect and call the add function

  int sum = client.add(1,1);
  
  // connection closed as we exit scope

}

Should any exceptions arise on the server side while invoking the requested object, an exception of type RCF::RemoteException will be propagated back to the client and thrown. Should any exceptions arise anywhere else on the server side, e.g., while serializing arguments, then the server will forcibly close the connection, and the client will throw an exception.

RCF will automatically handle a range of parameter types, including C++ primitive types (int, double, etc.), std::string, STL containers, and pointers and references to any of the previously mentioned types. Polymorphic pointers and references, and multiple pointers to single objects are correctly handled as well. Smart pointers are also supported (boost::shared_ptr, std::auto_ptr), and are the safest way of passing polymorphic parameters.

In CORBA, one can tag a parameter as in, out, or inout, depending on which direction(s) one wants the parameter to be marshaled. In RCF, the marshaling directions are deduced from the parameter type, according to the following conventions:

Value: in
Pointer: in
Const reference: in
Nonconst reference: inout

Nonconst reference to pointer: out

To use user-defined types as parameters or return values, some additional serialization code is needed. What that code is depends on which serialization protocols are being used; by default Boost.Serialization is used, and an example of passing a user-defined type would look like the following:

struct MyStruct
{
  int a;
  int b;
  int c;
  double d;
  std::string s;
  std::map <std::string, std::vector<std::string> > m;
  
  template<typename Archive>
  void serialize(Archive &archive, unsigned int version)
  {
    ar & a & b & c & d & s & m;
  }
  
};

RCF_BEGIN(MyInterface, "MyInterface")
  RCF_METHOD_R1(MyStruct, myfunc, const MyStruct &);
RCF_END(MyInterface);

Details

The server and client classes use BSD-style sockets to implement the networking, over TCP, and the whole framework has been compiled and tested on Linux, Solaris (x86 and SPARC) and Win32, using Visual C++ 7.1, Codewarrior 9.0, Borland C++ 5.5, and GCC 3.2. Building RCF requires v. 1.32.0 or later of the Boost library, although the only parts of Boost that need to be built are Boost.Serialization, and, for multithreaded builds, Boost.Threads. Multithreaded builds are enabled by defining RCF_USE_BOOST_THREADS before including any RCF headers.

To use RCF in your own application, you'll need to include the src/RCF.cpp file among the sources of the application, and link to the necessary libraries from Boost, along with OS-specific socket libraries (on Windows that would be ws2_32.lib, on Linux libnsl, etc.).

I've included a demo project for Visual Studio .NET 2003, which includes everything needed to compile, link, and run a server/client pair, with the exception of the Boost library, which needs to be downloaded and unzipped, but no building is needed.

Performance, as measured in requests/second, is highly dependent on the serialization protocol, and also on the compiler being used. Before turning to Boost.Serialization, I used a serialization framework of my own, with which I could clock around 3000 minimal requests/sec. using Visual C++ 7.1, and 3300 requests/sec. with Codewarrior 9.0, on a loopback connection on a 1400Mhz, 384Mb PC running Windows XP. GCC 3.2, on the other hand, was far slower. Using Boost.Serialization, however, I've been nowhere near these numbers; on average, it's around five times slower.

Conclusion

RMI is a well known concept in Java circles, what I've done here is to do something similar in C++, without all the complications of CORBA. If you like it, please tell me, if you don't, well, please tell someone else.... Jokes aside, any and all feedback is appreciated, all I ask is that if you grade the article, and do so with a low grade, then please leave an explanatory comment!

History

  • 8 Feb 2005 - First release.
  • 10 Mar 2005
    • Now includes a custom serialization framework, so you no longer have to use Boost's. Both serialization frameworks are supported though, use the project-wide RCF_NO_BOOST_SERIALIZATION and RCF_NO_SF_SERIALIZATION defines to control which ones are used. Default behaviour is to compile both.
    • Default client timeout changed to 10s.
    • Server can be configured to only accept clients from certain IP numbers.
    • Server can be configured to listen only on a specific network interface, such as 127.0.0.1.
    • Client stubs themselves are now properly serializable.
  • 4 April 2005

    More bugfixes, including:

    • Much-improved network performance (thanks to Jean-Yves Tremblay for finding the bug).
    • Shortened exception messages in release builds.
    • Client stubs automatically reset their connections when exceptions are thrown (eg for timeouts).
    • Finer-grained exception classes.
  • 11 July 2005
    • Stripped CVS folders from distribution.
    • Added user-definable callback functions to be called when RcfServer has started.
  • 16 Aug 2005
    • Added facilities for server-bound objects to query the IP address of the client that is currently invoking them. To see how it works, open the file RCF/test/Test_ClientInfo.cpp in the download. Just place a call to RCF::getCurrentSessionInfo().getClientInfo().getAddress(), and you'll receive a string containing the IP address of the client that is invoking the method.
  • 23 Sep 2005
    • Initialization and deinitialization of the framework can now be done explicitly, be defining the project-wide preprocessor symbol RCF_NO_AUTO_INIT_DEINIT, and then calling RCF::init() and RCF::deinit() at appropriate times. This is mainly useful for DLL builds, so that the DLL can be loaded without automatically initializing Winsock.
  • 19 Oct 2005
    • Compatible with Boost 1.33.0.
    • Added enum serialization to the built-in serialization engine, through the SF_SERIALIZE_ENUM macro. For an example of its use, see test/Test_Serialization.cpp.
    • Added a license.
  • 30 Jan 2006
    • Miscellaneous bugfixes.
    • The built-in maximum message size limit has been changed to 50 Kb. Look in src/RCF/Connection.cpp, line 374, if you need to change this.
    • I'll only be making sporadic maintenance releases of this version of RCF from now on. You can find the next generation of RCF here.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Jarl Lindrud
Australia Australia
Member
Software developer, ex-resident of Sweden and now living in Canberra, Australia, working on distributed C++ applications. Jarl enjoys programming, but prefers skiing and playing table tennis. He derives immense satisfaction from referring to himself in third person.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralRe: general questionsmemberJarl Lindrud8 Feb '06 - 11:51 

chrhol wrote:
For tunnelling your RCF protocol over an already established connection where I want to mix protocols from different systems. If I oversimplify, I would like to do something like this:

 
OK I see, that would be useful. I'll put it on the list of things to do. Might be a little while before I get around to dealing with it though, I'm a bit occupied at the moment getting RCF to run on Unix, but after that Smile | :)
 
Jarl.

Questionhow to make in solarismembernetboy_16816 Jan '06 - 16:16 
I tried to make demo in solaris for many times,but failed.Can you tell how to make demo in solaris ,please give me your Makefile,Thanks.
AnswerRe: how to make in solarismemberJarl Lindrud16 Jan '06 - 19:11 

It's been a while since I built RCF on solaris, but I used bjam, from Boost, to build it, instead of a makefile. I can use the same jamfile to build things on Windows/Linux/Solaris, with just about any compiler, and I find it a lot simpler than using makefiles.
 
It shouldn't make any difference, though, which build tool you're using. Which version of which compiler are you using? What errors are you getting? Compiler errors or linker errors?
 
Regards,
Jarl.

GeneralRe: how to make in solarismembernetboy_16817 Jan '06 - 2:39 
first ,thanks for reply in time.
 
my step as follws
 
1. using qmake create Makefile
 
#############################################################################
# Makefile for building: Client
# Generated by qmake (1.07a) (Qt 3.3.4) on: Tue Jan 17 20:59:31 2006
# Project: Client.pro
# Template: app
# Command: $(QMAKE) -o Makefile Client.pro
#############################################################################
 
####### Compiler, tools and options
 
CC = gcc
CXX = g++
LEX = flex
YACC = yacc
CFLAGS = -pipe -Wall -W -O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -m32 -march=i386 -mtune=pentium4 -fasynchronous-unwind-tables -DQT_NO_DEBUG -DQT_SHARED -DQT_THREAD_SUPPORT
CXXFLAGS = -pipe -Wall -W -O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -m32 -march=i386 -mtune=pentium4 -fasynchronous-unwind-tables -DQT_NO_DEBUG -DQT_SHARED -DQT_THREAD_SUPPORT -DRCF_NO_BOOST_SERIALIZATION
LEXFLAGS =
YACCFLAGS= -d
INCPATH = -I/usr/lib/qt-3.3/mkspecs/default -I. -I. -I$(QTDIR)/include
LINK = g++
LFLAGS =
LIBS = $(SUBLIBS) -L$(QTDIR)/lib -L/usr/X11R6/lib -lqt-mt -lXext -lX11 -lm
AR = ar cqs
RANLIB =
MOC = $(QTDIR)/bin/moc
UIC = $(QTDIR)/bin/uic
QMAKE = qmake
TAR = tar -cf
GZIP = gzip -9f
COPY = cp -f
COPY_FILE= $(COPY)
COPY_DIR = $(COPY) -r
INSTALL_FILE= $(COPY_FILE)
INSTALL_DIR = $(COPY_DIR)
DEL_FILE = rm -f
SYMLINK = ln -sf
DEL_DIR = rmdir
MOVE = mv -f
CHK_DIR_EXISTS= test -d
MKDIR = mkdir -p
 
####### Output directory
 
OBJECTS_DIR = ./
 
####### Files
 
HEADERS =
SOURCES = Client.cpp \
..\MyService.hpp \
..\RCF\RCF.cpp \
..\SF\SF.cpp
OBJECTS = Client.o \
MyService.o \
RCF.o \
SF.o
FORMS =
UICDECLS =
UICIMPLS =
SRCMOC =
OBJMOC =
DIST = Client.pro
QMAKE_TARGET = Client
DESTDIR =
TARGET = Client
 
first: all
####### Implicit rules
 
.SUFFIXES: .c .o .cpp .cc .cxx .C
 
.cpp.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
 
.cc.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
 
.cxx.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
 
.C.o:
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
 
.c.o:
$(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
 
####### Build rules
 
all: Makefile $(TARGET)
 
$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC)
$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJMOC) $(OBJCOMP) $(LIBS)
 
mocables: $(SRCMOC)
uicables: $(UICDECLS) $(UICIMPLS)
 
$(MOC):
( cd $(QTDIR)/src/moc && $(MAKE) )
 
Makefile: Client.pro /usr/lib/qt-3.3/mkspecs/default/qmake.conf /usr/lib/qt-3.3/lib/libqt-mt.prl
$(QMAKE) -o Makefile Client.pro
qmake:
@$(QMAKE) -o Makefile Client.pro
 
dist:
@mkdir -p .tmp/Client && $(COPY_FILE) --parents $(SOURCES) $(HEADERS) $(FORMS) $(DIST) .tmp/Client/ && ( cd `dirname .tmp/Client` && $(TAR) Client.tar Client && $(GZIP) Client.tar ) && $(MOVE) `dirname .tmp/Client`/Client.tar.gz . && $(DEL_FILE) -r .tmp/Client
 
mocclean:
 
uiclean:
 
yaccclean:
lexclean:
clean:
-$(DEL_FILE) $(OBJECTS)
-$(DEL_FILE) *~ core *.core
 

####### Sub-libraries
 
distclean: clean
-$(DEL_FILE) $(TARGET) $(TARGET)
 

FORCE:
 
####### Compile
 
Client.o: Client.cpp ../MyService.hpp
 
MyService.o: ..\MyService.hpp
$(CC) -c $(CFLAGS) $(INCPATH) -o MyService.o ..\MyService.hpp
 
RCF.o: ..\RCF\RCF.cpp ../RCF/ClientStub.cpp \
../RCF/Connection.cpp \
../RCF/Exception.cpp \
../RCF/InitDeinit.cpp \
../RCF/MethodInvocation.cpp \
../RCF/Multiplexer.cpp \
../RCF/Protocol/Protocol.cpp \
../RCF/Random.cpp \
../RCF/RcfServer.cpp \
../RCF/Token.cpp \
../RCF/Tools.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o RCF.o ..\RCF\RCF.cpp
 
SF.o: ..\SF\SF.cpp ../SF/Archive.cpp \
../SF/DataPtr.cpp \
../SF/deque.cpp \
../SF/Encoding.cpp \
../SF/Exception.cpp \
../SF/I_Stream.cpp \
../SF/ITextStream.cpp \
../SF/IBinaryStream.cpp \
../SF/INativeBinaryStream.cpp \
../SF/list.cpp \
../SF/map.cpp \
../SF/memory.cpp \
../SF/Node.cpp \
../SF/OBinaryStream.cpp \
../SF/ONativeBinaryStream.cpp \
../SF/OTextStream.cpp \
../SF/PortableTypes.cpp \
../SF/Registry.cpp \
../SF/scoped_ptr.cpp \
../SF/SerializeSmartPtr.cpp \
../SF/SerializeStl.cpp \
../SF/SerializeStaticArray.cpp \
../SF/SerializeDynamicArray.cpp \
../SF/SerializeFundamental.cpp \
../SF/SerializePolymorphic.cpp \
../SF/Serializer.cpp \
../SF/set.cpp \
../SF/SfNew.cpp \
../SF/shared_ptr.cpp \
../SF/Stream.cpp \
../SF/string.cpp \
../SF/Tools.cpp \
../SF/vector.cpp
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o SF.o ..\SF\SF.cpp
 
####### Install
 
install:
 
uninstall:
 
2. execute make and got such errors
 
make
make: *** No rule to make target `..\MyService.hpp', needed by `MyService.o'. Stop.
 
3. gcc version 4.0.0 20050519 (Red Hat 4.0.0-8)
 
can you tell me how to use bjam to build demo and show me you jamfile,thanks.

GeneralRe: how to make in solarismemberJarl Lindrud17 Jan '06 - 3:41 

First of all it's enough to just compile RCF.cpp and SF.cpp, they will pull in the rest of the source files themselves. So the rules for SF.o and RCF.o only need to compile SF.cpp and RCF.cpp, respectively.
 
The error that you're getting is because you're trying to compile MyService.hpp. You need to remove the MyService.o target, it will be included as a .hpp file into the server and client anyway.
 
Other than that, you should be fine. The jamfile that I use to build RCF test executables is in the /test directory, called "Jamfile". It has lots of targets, but you only need to build one at a time. I can type "bjam -sTOOLS=gcc -sBUILD=debug" Test_Minimal" to build a debug executable with the gcc compiler, for instance.
 
You'd need to build bjam first. It's part of boost, and there are instructions there on how to do it. Probably you only need to go to the ...boost\tools\build\jam_src and run the build.sh script.
 
Hope that helps,
 
Jarl.
 

GeneralRe: how to make in solarismembernetboy_16817 Jan '06 - 13:42 
thank you very much.
According to your guilding , I compiled demo in unix successfully.
GeneralRe: how to make in solarismemberJarl Lindrud17 Jan '06 - 19:13 

That's great. If you want, you can also compile and run the server on one operating system, and the client on another, and remote calls between the two will still work fine.
 
Jarl.

GeneralRe: how to make in solarismembernetboy_16817 Jan '06 - 21:53 
great! It do work properly!
 
I have another question. RMI can call a function from client to server,if I want to call a function from server to client, How can I do?
GeneralRe: how to make in solarismemberJarl Lindrud18 Jan '06 - 18:51 

The short story is, a server can't call a client... otherwise the client would have to be a server too.
 
So basically, you need to have two servers, one on each end.
 
By the way, I have a newer version of this framework available here[^]. It has a publish/subscribe feature that might be what you're looking for.
 
The new version only supports Windows so far, but that will change pretty soon. The next release should be out in a couple of weeks, and will run on both Windows and Unix OS's.
 
/Jarl.
 

GeneralSerialization FrameworkmemberReinhard Stoeckl9 Jan '06 - 5:56 
Hello!
I ve used SF not the boost lib to serialize. No have found that the executable moans about the size of the objects to be returned. It says:
..\rcf\src\rcf\connection.cpp(376): int __thiscall RCF::Connection::receive(void)::Thread-id=2436:
Timestamp(ms)=52327: THROW : RecvException: too much data: fd=1944, length=15592,
 
How can I overcome this error?
Many thanks in advance
Reinhard Stoeckl

GeneralRe: Serialization FrameworkmemberJarl Lindrud9 Jan '06 - 7:34 

Hi Reinhard,
 
There's currently a hardcoded 10K limit on message sizes, which is what you're running into. The message being sent to the server is ok, but the message coming back is apparently too big. You'll need to change the limit to something more appropriate; look in src/RCF/Connection.cpp, around line 375.
 
And yes, the next release will have a proper way of setting the maximum message size...
 
HTH,
 
Jarl.

GeneralRe: Serialization FrameworkmemberReinhard Stoeckl9 Jan '06 - 21:59 
Thank you very much for your quick response.
Reinhard
P.S.: I will keep you updated on success or failure.
GeneralRe: Serialization FrameworkmemberJarl Lindrud10 Jan '06 - 9:49 

Great!
 
/Jarl.

GeneralSerialization Frameworkmemberforums_mp16 Dec '05 - 18:28 
|| I used a serialization framework of my own,
|| with which I could clock around 3000 minimal requests/sec.
|| using Visual C++ 7.1, and 3300 requests/sec.
Would you be willing to share you serialization framework? Perhaps attach it to your zip file. This would be a viable alternative to the boost approach which will pull perfomance down tremendously.
 
-- modified at 0:28 Saturday 17th December, 2005
GeneralRe: Serialization FrameworkmemberJarl Lindrud16 Dec '05 - 19:53 

Actually, it's already part of the download... I just didn't update the text of the article. The serialization framework is in the include/SF directory, and RCF uses it by default.
 
/Jarl.

Questionconnection failedmember_BOBAH_29 Nov '05 - 21:33 
A RCF::Token object is assigned to each client. When the connections limit exceeds, the number if free tokens turns into zero and further connection attempts always fail.
The question is: how is it possible to put the free token back into the pool of free token explicitly ?? or just to break down the connection in other words ?? The most wanted way, as I see, is to leave the scope of the RcfClient object or maybe it is a call to some method like client.disconnect(). Please, enlight me, in such a bottleneck.
AnswerRe: connection failedmemberJarl Lindrud30 Nov '05 - 6:54 

Hi,
 
The best thing is to set up your appllication so that you bind interfaces directly to an instance:
 
RcfServer server(ip, port);
X x;
server.bind<I_X>(x);
 
Then all the clients will be accessing the same object, they won't be needing individual tokens, and the token limit will no longer play a role.
 
If you still need separate server objects for each client, then you could increase the number of tokens, if you want. Currently its hardcoded to 100, but you can change the value of NumberOfTokens in RcfServer.hpp to something bigger.
 
The tokens are returned to the pool when the corresponding server object is deleted. That only happens when a server object has been inactive for 60 seconds though, so after a RcfClient goes out of scope, it will still take a minute before the server decides to delete the object and recycle the token.
 
Hope that helps Smile | :) If possible, go with the first option, with all the clients sharing an object, and then the issue won't turn up at all...
 
Jarl.
 


QuestionRe: connection failedmember_BOBAH_5 Dec '05 - 19:54 
Hi, Jarl
 
I have got one more question about the RCF connections. How can I track the connection event - I need to have an opportunity to accept or to refuse pending connection. I have found out, that your framework can filter the ip-addresses of connecting clients, but I need a little bit more sophisticated server logics. For example: I have a data storage nested in server. The server has a "reader" interface and a "writer" interface. The idea is - the server must distinguish the client's access - "writer" interface must not be allowed for "everyone", except hard-fixed "priviledged" clients. And another sub-question - how can I implement the "many readers, one writer" concept - like the boost::read_write_mutex, using the RCF facilities ??
If it is possible to handle the both problems, I will be very happy Smile | :) .
 
Best regards, Vladimir.
AnswerRe: connection failedmemberJarl Lindrud6 Dec '05 - 19:43 

Hi Vladimir,
 
In test/Test_ClientInfo.cpp, there's an example of using the RCF::getCurrentSession() function, which can be called from within any server thread and gives information on the session that is currently being processed. Calling RCF::getCurrentSessionInfo().getClientInfo().getAddress()will give you a string representation of the client's IP address, and then from that you can decide whether you want to grant the client read or write access.
 
Hope that helps!
 
Jarl.

Questiondo you have plans to submit this to boost ?memberRodrigo Pinho Pereira de Souza29 Nov '05 - 13:54 
Great work,
 
In september, RMI was discussed in boost mailing list, and your code is very good candidate to enter in boost.
 
Did you ever think in change your code to boost coding guidelines and submit your code for evaluation in boost ?
 

 
Rodrigo Pinho Pereira de Souza
AnswerRe: do you have plans to submit this to boost ?memberJarl Lindrud30 Nov '05 - 7:05 

Thanks,
 
Yeah, it's been on my mind... I've been busy the past months rewriting and extending RCF, and when its released I'll see what the people at Boost think of it, and if they think it could eventually be accepted.
 
Can't say I'm looking forward to having to change the names of all my classes and functions, though, to agree with the Boost guidelines... Big Grin | :-D
 
Regards,
 
Jarl.

GeneralRe: do you have plans to submit this to boost ?memberRodrigo Pinho Pereira de Souza30 Nov '05 - 10:15 
Great,
 
You can take a look in asio library (http://asio.sourceforge.net). The author submits this library to boost. It's very interesting, I have been tested and I am using in my work.
 
In tests that I made, using this library, a simple HTTP server, accepted 30k connections at same time, it's very stable and very good candidate to enter in boost.
 
You can use this library to implement your RCF.
 
Another tip is for your library is:
- Implement something like Connection Points
- Use shared memory for use with local address.
 
regards
 
Rodrigo Pinho Pereira de Souza
GeneralRe: do you have plans to submit this to boost ?memberJarl Lindrud6 Dec '05 - 19:32 

Good points.
 
asio looks very interesting, hopefully that will make dealing with network specific details a lot easier.
 
Shared memory for communicating between processes on the same machine is also something that's been on my mind for a while, and is definitely on my to-do list.
 
Regards,
 
Jarl.

GeneralRe: do you have plans to submit this to boost ?memberandrea.carbone5 Dec '05 - 12:59 
This is a very good news!
I look forward to see this awesome piece of code into our favourite library!
Cheers
GeneralRCF::SerializationException: unsupported serialization protocol: N = 1member0xCCCC22 Nov '05 - 14:35 
I am getting an extremely long error message from an exception when I attempt to connect to a simple RCF server and issue one method call. The apparent gist of the message is
 
RCF::SerializationException: unsupported serialization protocol: N = 1
 
Any ideas?
 
ScoPi

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 6 Aug 2009
Article Copyright 2005 by Jarl Lindrud
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid