Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


ID: 26747, Transferring Object over the network

by Leonardo M. Ramé Email: martinrame@yahoo.com


This is a methodology for transferring objects between remote Delphi applications.
Download Details
FTP  download also available
CDN Login Required to Download. (You will be redirected to the login page if you click on the Download Link)
To download this, you must have registered:
A free membership

For Delphi, Version 1.0  to 1.0 839 downloads
Copyright: No significant restrictions


Size: 531,567 bytes
Updated on Fri, 20 Mar 2009 05:56:28 GMT
Originally uploaded on Fri, 20 Mar 2009 05:56:26 GMT
SHA1 Hash: 76D78BF851DE8F4ED8E5D57D5014882BAC30A584
MD5 Hash: 5922313D8368CFD04CB854A31843C4F9

    Explore the files in this upload

Description
Introduction
A couple of weeks ago, I was talking with a friend about a software he uses to book bus trips, he told me his company needs something similar, also he thinks I could adapt one of my applications to work like this program. The software is installed on more than one hundred sites, and it's connected to a central server over the Internet.

What resulted interesting to my friend was its speed, it works like if it was connected to a database in a local network (LAN), but it isn't. Also he added the server's Internet access is a cheap cable connection with ~300kb/s upload speed, and the clients connects using standard DSL or Cable connections. I asked what database and programming language the developers used. It's connected to a Firebird database and was programmed in C#, he replied. Then, I decided to try to replicate the scenario with a simple Delphi program.

My first attempt was a Delphi client connected to a Firebird 2.1 database using IBX controls. In my LAN, the app screams, but when I connect it over Internet it is as slow as a turtle. It seems to be that Firebird sends too much information over the network and it slows down the connection.

In my second attempt, I changed my app to use RemObject's SDK, I created an application server connected to the same database, it improved a lot...but if I'd choose the RO approach, I'd must rewrite the whole application.

Persistence

My application is based on classes derived from TPersistent, and uses TCollection/TCollection Item to store data, it doesn't uses any DbAware component and to persist it's data, it dynamically loads a Dll containing what I call a Database Access Driver who knows, thanks to RTTI and a (not so) complex mechanism, how to talk to the database. The Driver it's using currently, contains the IBX controls to talk to Interbase/Firebird, and I thought it could be great if I can create a similar Driver to use RemObjects SDK, but it turned out to be a real pain (and I hadn't time to investigate RO SDK in detail).

The application server

After the failed attemt to use RemObjects, I decided to create a simple Application Server, based on Indy's TCP Server control. The server should receive a request from the client asking for an object, or collection of objects, and the params to filter the result, then the server dynamically creates an instance of the requested class, fill its data, then converts it to XML and sends the result to the client, who must un-serialize the XML to reconstruct the instance.

I created the server side of the application, and found that the XML serialization part was too slow, resulting in more than 5 seconds for a collection of 500 items, maybe the serializer I used isn't optimized, and I didn't have time to improve by myself, so I decided to find a new serialization method...Thanks god and Roland Beenhakker I found this article on how to write and read the content of a TPersistent descendant to/from a stream. The first time I tested the trick Roland exposed in his article, I was shocked, it serialized my collection instantaneously, the de-serialization was also super fast.

How the server store the objects in the database?, it uses the same Data Access Driver the older Client Application used to connect to the database.

The client's Data Access Driver

Knowing the Serialization/Deserialization method I'll use for the application, I focused on writing a new Data Access Driver for connecting to the Application Server. The task was pretty easy, just serialize objects, then use the WriteStream and ReadStream method of Indy to send and receive the streamed objects to/from the server.

The real test

When I finished writing the new Data Access Driver, I decided to try it in a real environment, connecting the client from a remote machine to my local PC by using my home Internet connection. The results where amazing, the whole round trip only took 1.5 seconds!, impressive.

A little improvement

Knowing that the serialization/deserialization process is instantaneous, and the only possible bottleneck is the network. I decided to compress the streams sent over the network, and used InflateStream and DeflateStream from the great TurboPower Abbrevia library. The reduced stream size improved even more the results.

Side effects

As the data sent over the network is binary, it is also very (if not impossible) difficult to be intercepted and used by a unauthorized people. And if you are very concerned about security, after compressing the stream you can encrypt it.

One negative side effect of this approach, is that it only works with clients and servers written in Delphi and C++ Builder. To me, this is not a problem, because I maintain both, the server and the client, but if the server must be accessed by some other language, you could improve the protocol to let the server determine in which format the data should be transferred.

   Latest Comments  View All Add New

Move mouse over comment to see the full text

Server Response from: ETNACDC03