If you have defined RCF_FEATURE_BOOST_SERIALIZATION
, RCF will need to link to the Boost.Serialization library.
RCF does not link to any other Boost libraries.
Boost libraries have an auto linking feature that may cause your linker to look for the wrong file to link to. You can define BOOST_ALL_NO_LIB
, and then explicitly tell the linker which files to link to.
Yes. To export RCF functions from a DLL (Windows) or shared library (Unix), you will need to define RCF_BUILD_DLL
when building the DLL or shared library.
Historically there have been some header ordering issues with the Windows platform headers <windows.h>
and <winsock2.h>
. Including <windows.h>
will by default include an older version of Winsock, and makes it impossible to subsequently include <winsock2.h>
in the same translation unit.
The easiest workaround for this issue is to define WIN32_LEAN_AND_MEAN
, before including <windows.h>
.
Yes, if the following warnings are disabled:
Probably, but you may need to make minor modifications to RCF yourself, to accomodate platform specific issues, such as which platform headers to include.
On Windows, if you are using TCP transports, you'll need to link to ws2_32.lib. On Unix platforms, you'll need to link to libraries like libnsl
or libsocket
.
Yes.
Yes.
If you define external serialization functions in a header file, without the inline
modifier, and include them in two or more source files, you will get linker errors about duplicate symbols. The solution is to either add an inline
modifier:
, or to declare the serialization function in a header and define it in a source file :
If you include RCF headers into commonly used application headers of your own, you may notice an increase in build time, as the compiler will parse the RCF headers once for every source file that includes them.
You should only include RCF headers when you need to - in other words, only include them into source files that use RCF functionality. In your application header files, you should be able to use forward declarations, rather than including the corresponding header files.
For example, if you are defining a class X
with a RcfClient<>
member, you can forward declare the RcfClient<>
, and then use a pointer for the member:
You can then include X.h
anywhere in your application, without including any RCF headers.
Whenever an outgoing TCP connection is made, a local port number has to be assigned to the connection. On Windows XP, those local ports (sometimes referred to as ephemeral ports) are by default assigned from a range of about 4000 port numbers.
If you create many RcfClient<>
objects, with TCP endpoints, you will eventually exhaust the available ports, as Windows holds on to them for a short while after the connection is closed.
You should use as few TCP connections as possible (reuse RcfClient<>
objects instead of creating new ones). There are also registry settings on Windows XP that alleviate the issue. Locate the following key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
, and set
TcpNumConnections = 0x800, MaxUserPort = 65534
After restarting, the system will allow an expanded range of ephemeral ports.
This problem is only relevant to older versions of Windows. Windows Vista and later use an expanded range of ephemeral ports.
Probably because RCF::deinit()
has not yet been executed.
On Windows, RCF uses I/O completion ports. See Scalability.
For local RPC on Windows, RCF supports named pipe transports (RCF::Win32NamedPipeEndpoint
), which are backed by shared memory.
For local RPC on Unix, RCF supports Unix local socket transports (RCF::UnixLocalEndpoint
).
Yes - see IPv4/IPv6.
Either run remote calls on a non-UI thread, or use progress callbacks to repaint the UI at short intervals. See Client Progress Notification.
Use a progress callback (see Client Progress Notification). You can configure the callback to be called at any given frequency, and when you want to cancel the call, throw an exception.
You can't call RCF::RcfServer::stop()
from within a remote call, because the stop()
call will wait for all worker threads to exit, including the thread calling stop()
, hence causing a deadlock.
If you really need to stop the server from within a remote call, you can start a new thread to do so:
Make RcfClient<>
a friend of your implementation class:
RcfClient<>
instances?You can move network connections from one RcfClient<>
to another. See Transport Access.
Call RCF::getCurrentRcfSession().disconnect()
in your server implementation.
RcfClient<>
object connect to the server?A RcfClient<>
will only establish a network connection once you initiate a remote call. If you want to establish a network connections without actually making a remote call, use RCF::ClientStub::connect()
.
Call RCF::getCurrentRcfSession().getClientAddress()
in your server implementation.
When a client disconnects, the associated RCF::RcfSession
on the server is destroyed. You can use RcfSession::setOnDestroyCallback()
, to notify your application code when this happens.
Yes. As long as a subscriber is able to initiate a connection to the publisher, it will receive published messages. The publisher will never initiate any network connection back to a subscriber.
The publisher cannot know this, because messages are published using one-way semantics.
Use subscriber disconnect notifications. See Subscribers.
You can also poll for connectedness using RCF::Subscription::isConnected()
.
Pointers can't be used as return types in RCF interfaces, because there is no safe way of marshaling them.
Pointers can be used as parameters in RCF interfaces, although most of the time you are better off either using references, or one of the smart pointer types available in C++.
Specify a port number of zero in the RCF::TcpEndpoint
object passed to the RCF::RcfServer
constructor. After the server is started, retrieve the port number by calling RcfServer::getIpServerTransport().getPort()
.
Use servant binding names. See Adding Servant Bindings.
In the RCF::TcpEndpoint
passed to your RCF::RcfServer
, you need to specify 0.0.0.0
as the IP address, to allow clients to access it through any network interface. By default 127.0.0.1
is used, which will only allow clients on the local machine to connect.
Probably because your program has a global static object whose destructor is trying to destroy a RcfClient<>
or RcfServer
object (or some other RCF object), after RCF has been deinitialized.
Make sure you destroy all RCF objects before deinitializing RCF.
RCF will serialize and deserialize C++03 enums automatically, as integer representations.
C++11 enum classes require a helper macro SF_SERIALIZE_ENUM_CLASS()
(see Standard C++ Types).
Yes, see Serialization To and From Disk.
See File Transfers.
asio::io_service
used by the RCF server?You can call AsioServerTransport::getIoService()
:
The io_service
will be destroyed when the RcfServer
is stopped.
You can use custom request user data (RCF::ClientStub::setRequestUserData()
, RCF::RcfSession::getRequestUserData()
) , to pass application specific data from the client to the server. See Custom Request and Response Data.
std::wstring
objects between Linux and Windows?Yes. std::wstring
objects are assumed to be represented in UTF-32 on Linux, and UTF-16 on Windows, and RCF will encode them as UTF-8 when serializing.
std::string
objects between Linux and Windows?Yes. RCF serializes std::string
as a sequence of 8-bit characters, so it doesn't matter whether the encoding is ASCII, ISO-8859-1, UTF-8, or anything else.
The following code snippet will cause compiler errors:
Because of a C++ language idiosyncracy, the declarations of client
and server
are actually interpreted as function declarations, taking a RCF::TcpEndpoint
parameter named port
. C++ compilers interpret the declarations this way to maintain backwards compatibility with C.
To clear up this ambiguity, extra parentheses are needed around the RCF::TcpEndpoint
:
This quirk of the C++ language is sometimes referred to as "C++'s most vexing parse".