## Appendix - FAQ

### Building

#### Why is my program trying to link to a Boost library?

If you have defined `RCF_USE_BOOST_SERIALIZATION`, RCF will need to link to the Boost.Serialization libraries.

If you have defined `RCF_USE_BOOST_FILESYSTEM`, RCF will need to link to the Boost.Filesystem and Boost.System libraries.

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.

#### Can I compile RCF into a DLL?

Yes. To export RCF functions from a DLL you will need to define `RCF_BUILD_DLL`.

#### Why do I sometimes get compiler errors when I include <windows.h> before RCF headers?

Because of 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>`.

#### Does RCF compile warning free on level 4 on Visual C++?

Yes, if the following warnings are disabled:

    C4510 'class' : default constructor could not be generated
    C4511 'class' : copy constructor could not be generated
    C4512 'class' : assignment operator could not be generated
    C4127 conditional expression is constant

#### Can I run RCF on platform XYZ?

Probably, but you may need to make minor modifications to RCF yourself, to accomodate platform specific issues, such as which platform headers to include.

#### Why do I get linker errors?

On Windows, if you are using TCP transports, you'll need to link to ws2_32.lib. On *nix platforms, you'll need to link to libraries like `libnsl` or `libsocket`.

#### Does RCF support Visual C++ 6 (Visual Studio 98) ?

No. RCF 1.3.1 is the last RCF version that supports Visual C++ 6.

#### Does RCF support 64 bit compilers?

Yes.

#### Does RCF support Unicode builds on Windows?

Yes.

#### Why do I get duplicate symbol linker errors for my external serialization functions?

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:

    // X.hpp
    inline void serialize(SF::Archive & ar, X & x)
    {
        ...
    }

, or to declare the serialization function in a header and define it in a source file :

    // X.hpp
    void serialize(SF::Archive & ar, X & x);

    // X.cpp
    void serialize(SF::Archive & ar, X & x)
    {
        ...
    }

#### How do I reduce build times for my application?

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 happens to include 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:

    // X.h
    template<typename T>
    class RcfClient;

    class SomeInterface;
    typedef RcfClient<SomeInterface> MyRcfClient;
    typedef boost::shared_ptr<MyRcfClient> MyRcfClientPtr;

    class RcfServer;
    typedef boost::shared_ptr<RcfServer> RcfServerPtr;

    // Application specific class that holds a RcfClient and a RcfServer.
    class X
    {
        X();
        MyRcfClientPtr mClientPtr;
        RcfServerPtr mServerPtr;
    };

    // X.cpp
    #include "X.h"
    #include <RCF/RcfClient.hpp>
    #include <RCF/RcfServer.hpp>

    X::X() :
        mClientPtr( new RcfClient<SomeInterface>(...) ),
        mRcfServerPtr( new RcfServer(...) )
    {}

You can then include `X.h` anywhere in your application, without including any RCF headers.

### Platforms

#### Why do I run out of socket handles on Windows XP?

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 (use the same `RcfClient<>` object 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.

#### Why does my leak detector think there is a leak in RCF?

Probably because `RCF::deinit()` has not yet been executed.

#### Is RCF's TCP server implemenation based on I/O completion ports?

On Windows, yes. See Performance.

#### Does RCF support a shared memory transport?

For local RPC, RCF supports named pipe transports (`Win32NamedPipeEndpoint`), which are backed by shared memory.

#### Does RCF support IPv6?

Yes - see Transport configuration.

### Programming

#### How do I keep my user interface from freezing when there's a remote call in progress?

Either run remote calls on a non-UI thread, or use progress callbacks to repaint the UI at short intervals. See Progress callbacks.

#### How do I cancel a long-running client call?

Use a progress callback (see Progress callbacks). You can configure the callback to be called at any given frequency, and when you want to cancel the call, throw an exception.

#### How do I stop a server from within a remote call?

You can't call `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:

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

    RCF::RcfServer *gpServer = NULL;

    class Echo
    {
    public:
        std::string echo(const std::string &s)
        {
            if (s == "stop")
            {
                // Spawn a temporary thread to stop the server.
                RCF::Thread(boost::bind(&RCF::RcfServer::stop, gpServer));
            }
            return s;
        }
    };

    int main()
    {
        Echo echo;
        RCF::RcfServer server( RCF::TcpEndpoint(0));
        server.bind<I_Echo>(echo);
        server.start();

        gpServer = &server;

        int port = server.getIpServerTransport().getPort();
        // This call will stop the server.
        RcfClient<I_Echo>(RCF::TcpEndpoint(port)).echo("stop");

        return 0;
    }

#### How can I make remotely accessible functions private?

Make `RcfClient<>` a friend of your implementation class:

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

    class Echo
    {
    private:

        friend RcfClient<I_Echo>;

        std::string echo(const std::string &s)
        {
            return s;
        }
    };

#### How do I use a single TCP connection with several `RcfClient<>` instancesd?

You can move network connections from one `RcfClient<>` to another. See Access to underlying transport.

#### Can I publish/subscribe through a firewall?

Yes. As long as a subscriber is able to initiate a connection to the publisher, it will receive published messages.

#### Why can't I use pointers in RCF interfaces?

Pointers can't be used as return types in RCF interfaces, because there is no safe way of marshaling them. Pointers can however be used as in parameters to a remote call, and behave essentially like a reference.

#### How do I start a TCP server on the first available port on my machine?

Specify a port number of zero in the `RCF::TcpEndpoint` object passed to the `RcfServer` constructor. After the server is started, retrieve the port number by calling `RcfServer::getIpServerTransport().getPort()`.

#### How do I forcibly disconnect a client from the server?

Call `RCF::getCurrentRcfSession().disconnect()` in your server implementation.

#### How do I know that a client has received a published message?

The publisher won't know, because messages are published using oneway semantics.

#### How do I expose several servant objects having the same interface?

Use servant binding names. See Binding servant objects.

#### Why is my server only accessible from the local machine, and not across the network?

In the `RCF::TcpEndpoint` passed to your `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 restricts clients to running on the same machine as the server.

#### At what point does a `RcfClient<>` object connect to the server?

When `getClientStub().connect()` is called, or a remote call is made.

#### Why does my program crash or assert when exiting?

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.

#### How do I determine what IP address a client is connecting from?

Call `RCF::getCurrentRcfSession().getClientAddress()` in your server implementation.

#### How do I serialize enums?

SF will serialize and deserialize enums automatically, as integer representations.

#### Can I use SF to serialize objects to and from files?

Yes, see Serialization.

#### How do I send a file using RCF?

See File Transfers.

#### How does a subscriber know if a publisher has stopped publishing?

You can use disconnect notifications, or poll the subscriber for connectedness. See Publish/subscribe.

#### How can I access the internal `asio::io_service` used by the RCF server?

You can call `AsioServerTransport::getIoService()`:

    #include <RCF/AsioServerTransport.hpp>

    RCF::RcfServer server( ... );
    RCF::I_ServerTransport & transport = server.getServerTransport();
    RCF::AsioServerTransport & asioTransport = dynamic_cast<RCF::AsioServerTransport &>(transport);
    boost::asio::io_service & ioService = asioTransport.getIoService();

The `io_service` will be destroyed when the `RcfServer` is stopped.

#### How do I detect client disconnections, from server-side code?

When a client disconnects, the associated `RcfSession` on the server is destroyed. You can use `RcfSession::setOnDestroyCallback()`, to notify your application code when this happens.

    void onClientDisconnect(RCF::RcfSession & session)
    {
        // ...
    }

    class ServerImpl
    {
        void SomeFunc()
        {
            // From within a remote call, configure a callback on the current RcfSession.

            RCF::getCurrentRcfSession().setOnDestroyCallback( boost::bind(
                onClientDisconnect,
                _1));
        }
    }

`boost::bind()` can be used to pass extra arguments to the callback function.

#### How do I pass a security token from the client to the server, without changing the RCF interface?

You can use user data slots (`ClientStub::setRequestUserData()`, `RcfSession::getRequestUserData()`) , to pass application specific data from the client to the server. See Per-request user data.

#### Can I send `std::wstring` objects between Linux and Windows?

In RCF 1.2 and earlier, Unicode strings stored as `std::wstring`, were serialized as a sequence of `wchar_t` characters. This would cause serialization errors if the client and server were running on platforms with different `std::wstring` encodings, such as Linux and Windows.

In RCF 1.3 and later, `std::wstring` is serialized in UTF-8 encoding, with conversions to and from UTF-16 or UTF-32, depending on the platform. See Advanced Serialization - Unicode strings.

#### Can I send UTF-8 encoded `std::string` objects between Linux and Windows?

Yes - SF serializes `std::string` a sequence of 8-bit characters, so it doesn't matter whether the encoding is ASCII, ISO-8859-1, UTF-8, or anything else. Your application just needs to be aware of the encoding of its own strings,

### Miscellaneous

#### Why are there double parentheses in so many of the examples?

The following code snippet will cause compiler errors:

    int port = 0;
    RcfClient<I_Echo> client( RCF::TcpEndpoint(port));
    RCF::RcfServer server( RCF::TcpEndpoint(port));

    // Will get compiler errors on both of these lines...
    client.getClientStub();
    server.start();

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, we need to put in extra parentheses around the `RCF::TcpEndpoint`:

    int port = 0;
    RcfClient<I_Echo> client(( RCF::TcpEndpoint(port)));
    RCF::RcfServer server(( RCF::TcpEndpoint(port)));

    // Now its OK.
    client.getClientStub();
    server.start();

This quirk of the C++ language is sometimes referred to as "C++'s most vexing parse".