Fast and reliable COM-Tools for developers

dhRPCServer

This is actually the most mature part (developed and hardened over years) in our Toolset and contains not only an XCopy-deployable Serverpart, it comes of course also with an appropriate RPCClient-Part too. Both parts, the clientside RPC-Class (cRPCConnection) -

and the serverside ThreadPool (entrypoint here is the cRPCListener-Class) are compiled into the dhRichClient3.dll now - and usable this way in your own, selfwritten hosting-Apps.
 

The communication between the Client- and the Server-Part is done over TCP/IP-sockets whilst using a fast binary protocol (and one single, definable port only).

Basically it is the "barebone-version" of our larger dBAS-Applicationserver (mentioned here), optimized and tuned over the last years.

The current version of the RPC-Environment is 3.0.22.


Downloads:

As said above, the Binaries for the RPC-functionality now come as a 3-Dll-Set, contained in the "official" dhRichClient3-Download.

The VB6-Demo-Sources of the Toolset implement different RPC-Demo-Scenarios - up to an Multi-User-Demo, which covers a concurrent DB-scenario, transferring disconnected SQLite-Recordsets - so the RPC-functionality of the toolset, combined with the SQLite-Wrapper-Classes and their superfast serialization-features, allows you to host and decouple the fast SQLite-Desktop-Engine from the clientside - and this combination formes a very well performing SQL-Server-engine (small and XCopy-deployable).

 

Here's a screenshot of the RPCServer, hosted on a Linux-machine and currently

"stressed" by two concurrent DB-Clients (one running on XP and one on Linux).


Features:

1.)

One goal of the developement was: simplicity (no mysterious DCOM/COM+

puzzling anymore, regarding SecurityConfig, UserRights, Registration).

Start RPCServer.exe (the RPC-Service-Controller) and from there start

dhRPCService.exe (either as UserProcess or as Service).

Now start the ClientDemo (RPCDemoClient.exe) from inside the Client-

RPCDirectory - eh voilà - it should connect and work. Now test Cross-

Machine Calls in your LAN. Simply copy both, the Server- and Client-

Folder to the new Host, start the Server there, start the Client and

try to Cross-Connect from both Machines (using the appropriate HostIPs/

HostNames - it should work too. No MS-Management-Console, no DCOMConfig,

no Proxy-/Interface-Creation/Registration.

Just look at the Sources - The Code for wrapping basic SQLite-Read/Write-

functionality needs ca. 50 lines in the server-class (DBServer.Dll) and ca.

30 lines in the clientside Wrapper-Class. We have builtin support for (clientside)

Debugging of the whole RPC-Roundtrip - simply step through all of your Client-

and Server-side Code-Lines. As soon as your Server-Code is stable, you can

compile your Server.Dll and simply put it into the \RPCDlls-Folder in your

Server-Directory (no need to register anything), switch off DebugMode at the

Clientside and you can access your Dll at the "real server".


2.)

As already mentioned above, (and that's not only working in our Demo,

it will work for your ClientCalls and your ServerDlls too), there's no

need, to register Interfaces for our COM-Calls across Machine-Boundaries

(neither at the client-side, nor at the server-side) anymore - we use

LoadLibrary + LoadTypeLibEx + DllGetClassObject, to instantiate from

the Filesystem directly.

Wrapper-Classes at the client-side have to be written by hand, but

they need very small Implementation-Effort (look at the Demo-Source)

and can be Private Classes.


3.)

All Types, that are accepted by a (VB-)Variant-ParamArray can be transported

(the whole bunch of VBs "simple" Types and their Arrays).

Objects (altough not Object-Arrays) are supported too, as long as they

support the IPersistStream-Interface (most interesting in this regard

are ADO-Recordsets, wich allow this "Out-Of-The-Box").

No ANSI-Conversion is performed for String-Types, so we avoid problems

with different locales (the RPC-Requests offer full UniCode-Transport).

Full support for ByRef-Params - non-changed Byref-Params (especially

Arrays of simple Types and Recordsets) are detected by our Serializer

automatically, and do not waste bandwidth regarding their unnecessary

backtransport to the Client.


4.)

Fast transfers using an efficient binary Socket-Protocol, consuming only

one single Port (DCOM uses a complete Port-Range). Port 80 (http) can be

used also, because the server answers to http-Gets and -Posts correctly.

Our ZLib-based Compression-Feature becomes very usefull in Low-Bandwidth-

-Scenarios (Internet-Connections).

Strong-Encryption is also possible at Protocol-Level. We use Diffie-

Hellman-Authentication and avoid man-in-the-middle-attacks per Challenge/

Response using Public-/Private KeyPairs. After the DH-KeyExchange/Auth.

the serialized Packets are encrypted using 256Bit ArcFour-Encryption,

wich is very fast and generates not much Call-Overhead. But if you want

to work over your own VPNs or SSH-Channels, you can simply switch it off.

I've also tested RPCs succesfully in a Putty-initiated (Open-)SSH-Session

per DSL and all was working fine.


5.)

Authorization is possible at RPC-Level (or better: Connection-Level -

for RPC-Level-Impersonation-Switches you would have to reconnect before

each Call with another ServerKnown-Account). This feature allows, to use

server-side resources (NetWork-Shares, SQL-Servers) with the appropriate

Win-User-Rights for each Client-Connect (respective Request) independently.

The Server supports a ForceAuthentication-Switch, so that unauthorized

Connection-Attempts are blocked (disconnected instantly). It is also

possible, to restrict the Windows-Authentication to the Members of a self-

defined Group(name) only.


6.)

TimeOuts at Method-Call-Level. TimeOuts are handled properly, even if

the bandwidth is limited (on slower internet-connections there will be

a packetbased "TimeOut-Retriggering"), so that you can define your TOuts

very narrow to the duration of the pure server-side Method-Call, no need

to take latencies or slow transfers due to low bandwidth into respect.


7.)

The Server is storing requests in a Job-Queue and gives them from there

to a WorkerThread-Pool, wich finally does the processing. The ThreadPool-Size

can be changed dynamically whilst the server is running. The Server hardly

terminates a running request (on its WorkerThread) after RPC-Timeout + 0.5

sec without losing stability, a terminated Thread is replaced with a fresh

WorkerThread-Instance.


8.)

Stateful Objects: Altough Objects in the "Server-Layer" normally should

be called in a stateless manner, there are often scenarios, where you

want to "pin" values between requests (complex transactions come to mind,

or the requirements of enhanced session-management), or you simply want to

let a serverside resource opened between the calls (e.g. COM-Ports, etc.).

For this purpose we allow to instantiate serverside Singletons (reachable also

from outside the RPC-Hosting-process).

These Objects can be defined and created from your own server-side DLL-

Classes. They are instantiated on separate threads beside the WorkerThread-

Pool (also done without using the registry - as usual here). They allow

marshaled "In-Call-Order-Access" from the "normal" RPCs (wich run on

their own WorkerThreads). This Pipe-based Marshaling takes care, that

parallel requests from different WorkerThreads are queued. But look at our

Demo, you will find commented examples there.


************************** Limitations ***************************

Max Client-Connects: 1024

Max ThreadPool-Size: 64

Max Client-Req-Size: 4,000,000 Bytes (see comments in the COM-Demo)

Max Servr-Resp-Size: 8,000,000 Bytes (see comments in the COM-Demo)


Performance:

Performance is very good, after improving the Variant-Parameter-Serialization-

Routines the new server-classes in dhRichClient3 can now process around 12000

small COM-Requests per second. (measured under heavy load on a "cheap" Dual-

Athlon-CPU (2.4GHz), using our Demo-Client and its String-Reflection-Loop from

multiple ClientMachines in a GBit-LAN).

Performance for a single connected Client is around 3500 COMReq/sec, so a

simple Calls Roundtrip-Time calculates (as a consequence) to around 0.3ms.


Combined with the SQLite-WrapperClasses (look at the Demos from the Download-

Links above) the Server reaches outstanding Multi-User-Results.
You can expect ca. 600 Responses/sec, serving 'Select * from Orders' or ca. 2000 Responses/sec serving 'Select * from Customers' in form of disconnected and serialized Recordsets- stresstested from multiple Clients against a "Standard-NWind.db' on a simple Dual-Athlon-CPU (2.4GHz - SATA 7200/min, 1024 MB Ram, 1GBit-LAN, FastLZ-Protocol-Compression and -Encryption enabled).


One additional note:

I've just tested the whole thing (DemoClient-App and Server) on an actual

Linux-Box (Debian-based) with the current Wine-Version 1.1, and there's

absolutely nothing (regarding the RPC-Calls), that doesn't work as expected

(no Server-Crashes, no Memory-Leaking, nothing) - even the ADO-Recordset-

Calls finished succesfully (tested Linux->Linux and XP->Linux scenarios).

So hosting your '*.mdb', your SQLite-DBs (the Server works best with SQLite)

or a "real" SQL-Server like PostGres (wich has its own OleDB-ADOProvider -

Firebird also) together with the server-side Logic on an inexpensive

Linux-based Internet-Hoster becomes possible now.

Linux was faster for Remote-Calls with large Content (not much, but

faster ;-) - probably due to the very good Wine-Translation into the

Linux-Socket-Stack). As expected, it has larger COM-Overhead regarding

Class-Instantiation and Method-Invoking-ByName - so our Stressing-Loop

from different DemoClients (small Com-Calls with very few Data)

sumed up to around 8000 Server-Responses per second under heavy load (where

the XP-Box had 12000). But the more realistic ADO-Recordset-Call was finished

after 7msec (XP 6ms) - so this relativates the Call-Overhead (factor 3) to

some factor 1.2 for usual (DB-)calls.

Despite the COM-Overhead, these are very good values - I was impressed.

Thanks to the Wine-folks, who made this possible!