Cleaner than SOAP, jazzier than JSON, and better than the REST!
VB6 has a powerful serialization object knwn as the PropertyBag. The huge improvement over the VB5 version of this object (which VB6 still supports for compatibility reasons) was the addition of the Contents property. This made it possible to use a PropertyBag as a custom serialization tool.
There are any number of reasons why you might want to perform efficient custom object serialization. The one demonstrated here is for implementing a fast, custom, binary client-server message format - that can marshall persistable objects!
Beats the pants off slow and crappy Web Services by far.
This demonstration consists of a multi-client TCP server DemoServer, a TCP client DemoClient, and a custom persistable object library PBDemoTreeLib supplying a Node class that can be used to create lists and trees.
Here I am using TCP port 8018 but you can easily change that or make it variable at runtime.
There is also a small helper project MakeMDB which must be run once to create the Jet 4.0 database used by DemoServer.
This is a simple TCP server that can perform several operations or functions (I'm calling them "methods" here):
DemoServer expects clients to make a request and await a response before making another request. However multiple clients are free to make overlapping requests of course. It is also quite possible to create "methods" that can update a database as well as simply make queries as I do here.
Add(ByVal A As Double, ByVal B As Double) As Double - adds two values and returns their sum.
Dir(ByVal Dir As String) As PBDemoTreeLib.Node - looks up a requested directory and returns a list of the files under that directory.
HomeStates() As ADODB.Recordset - retrieves a list of "Home State" fields from the "HomeStates" table in the database and returns the disconnected Recordset.
PresidentsAll() As ADODB.Recordset - retrieves the entire "Presidents" table from the database as a disconnected Recordset.
PresidentsWhereHomeState(ByVal HomeState As String) As ADODB.Recordset - retrieves "Presidents" table rows where "Home State" = HomeState.
When DemoServer starts it is seen on the server machine as a Notification Area ("tray") icon. The icon's ToolTip shows the number of connected clients. TCP errors are Debug.Print-ed when running in the IDE and any error causes the server to shut down. There is one item on the icon's context menu, used to exit from the server (close it).
This is a simple TCP client. It accepts a server host address (name or IP address) and when the Connect button is clicked it connects to the server.
Upon connection it performs a HomeStates() call to populate a List control. From there you can supply values and perform any of the other operations. To exit simply close the application as usual.
A simple helper project. Open it in the VB6 IDE, run it. It will load CSV data, creating a Jet 4.0 database "USPresidents.mdb" which you should move or copy into the Server folder where DemoServer expects to find it.
This project isn't needed except for this one function.
This project is a DLL used by the client and the server to provide a persistable class Node. Node can be used to create and manipulate simple trees and lists with simple Name and Value properties.
It also demonstrates one common way of persisting VB6 Collection objects, which are not themselves persistable.
This library is included and used in the demo to show how you can use PropertyBags to marshall customs objects and object models (DOMs, etc.). Here I only use it for a simple list, the value returned by the Dir() method.
Communication Protocol Used Here
This protocol is an application layer on top of TCP. It could easily be used with other transports: HTTP, SMTP (email!), MSMQ, Named Pipes, etc.
Each message consists of two fields:
Messages making server requests have a property in the PropertyBag named "Method" identifying what is being requested. They will also contain other properties reprsenting arguments of the method.
Length - Long value, size of Contents in bytes.
Contents - Byte array, value of a PropertyBag.Contents property.
Messages returning server responses have a property in the PropertyBag named "Method" identifying what method generated the response. There are also additional properties containing the result of the method or any changed, or "ByRef" argument values.
There is also a simple error response possible. It has "Method" set to the value "Error" and has additional error number and description properties.
Building This Demo
Note: Make sure you always run the VB6 IDE with elevated permissions. On XP and earlier this means running under an admin user. In Vista and later this means using "Run As" or an elevation manifest for VB6.exe.
Start by building PBDemoTreeLib:
- Open this project in the VB6 IDE.
- Make and Save, then exit.
- Drag PBDemoTreeLib.dll and drop it onto UnregDLL.vbs to unregister it.
- Rename PBDemoTreeLib.dll to ref-PBDemoTreeLib.dll.
- Open the project once more.
- Go into Project|Properties... and on the Components tab of the dialog set Binary Compatibility and set the reference library to ref-PBDemoTreeLib.dll.
- Make and Save again, then exit.
Next open and run MakeMDB (inside the Server folder). Copy or move the resulting MDB file into the Server folder.
Build DemoServer, then DemoClient. Same process for each:
- Open the project in the IDE.
- Set a reference to PBDemoTreeLib ("A Demo Public Class Lib for PBDemo").
- Make and Save, exit.
Running The Demo
Create setup packages for DemoServer and DemoClient if you want to deploy them onto separate machines. Be sure to include the "USPresidents.mdb" file in your DemoServer package. The PDW supplied with VB6 is fine for this.
Copy and install your deployment packages on your test machines as required.
Then you can run DemoServer. It should appear in the Notification Area and you may get a firewall alert you will need to approve.
Then run one or more copies of DemoClient. Put the server's Host Addres in the textbox and click Connect. You should see updates in the status bar and very soon the States listbox should be populated.
Now you can supply various inputs and perform the various options.
End the clients normally. End the server via the tray icon's popup menu.