viksoe.dk

Full Client / Server sample

Full Client / Server sample


This article was submitted .


Due to a change in my job situation I have been studying network programming for the last few weeks.
To get up to speed I bought a book about Windows Network programming; it's actually only my 2nd book I've bought in about 5 years and it has already got a place beside my copy of "ATL Internals".

This is a C++ sample of doing a full client/server application. I call it full because it features many things you would normally add to such an application - and then some. But since I haven't previously done much network programming, it's still just an experiment.
The server application is highly depending on multi-threading and it supports several protocols for communication with client applications.

The Client

The client is a crude application written in Visual Basic; it allows you to test the server. It uses some of my other VB components for network communication. It uses my Mail Slot component, the MS Winsock ActiveX control for TCP/IP communication and a lot of other Microsoft components such as MSXML and ADO.

Server as a NT Service

The server part runs as a Windows NT service. Most of it is written in straight C++.
Running as a service introduces a few NT security problems and some debugging considerations as well:
Security problems arises when you're trying to access network resources (such as databases). Because a service is usually logged on as the local administrator account there is no access to many outside resources.
In addition, debugging can be particular troublesome with NT services so I used the ATL 3.0 service code to implement it. It allows you to run the application as a stand-alone application as well.

Data storage

I found that there was no need for a complex data storage layer in this simple sample, so data (a bunch of strings) is stored in a thread synchronized vector.
Usually you would add a database layer or a driver to some hardware. Because this server is highly multi-threaded there are some problems with doing this, but I'll investigate that later.

Server detection

The server features a small "server detection" component, which allows clients to list the available servers running on the network. It does this using mailslots. I've already discussed mailslots in my VB Mail Slot component.
It's done using 2 mailslots and a simple communication contract. Since mailslots is an unreliable protocol, there may be restrictions on the completeness of result.

Custom protocol

The server implements its own simple protocol on top of existing "low-level" network protocols. This way the server is not aware if it's talking TCP/IP or using another transport protocol to the client.
This kind of abstraction is important if you want to support several transport protocols without writing complex code over and over again. The protocol is kept simple. My server only supports very very simple updates from a simple list of string.
GET X
SET X value
where X is the item index (goes from A to Z). It is a basic command/response protocol: You send a new-line terminated string to server and it returns the result as a new string.

Named Pipes

Named Pipes communication has a delightfully simple API.
The fact that MS SQL Server defaults to Named Pipes assured me that it was a powerful alternative to the traditional socket services.
Named Pipes uses Microsoft's own redirector to route packages and is protocol independant. In addition, it allows you to integrate Windows NT security checking into the connection stream which is a really cool thing.
The server accepts incoming requests through Named Pipes. For every client that attaches to the Pipe it spawns a new thread and completes the exchange of data in that. Restricting the number of threads is also possible to avoid overloading the server with simultanious requests.

TCP/IP

There is also a standard socket implementation.
Sockets on TCP/IP is the most preferred application server implementation today.
I'm not using advanced socket models, such as overlapped IO. As mentioned, it uses multi-threading to handle incoming requests. But as long as the server is only intended for a limited number of simultanious connections that's just fine.

HTTP Proxy (IIS ISAPI)

This one is based on an idea from the company I used to work for. It adds HTTP protocol support to the server using an extension placed on a web-server. In this case, I've written an IIS ISAPI module.
Because there are many interesting topics around this component, I put it in its own article.

OLE DB and ADO

To expose the server data to high-level programming languages, such as MS Visual Basic, I've also included a small OLE DB Provider. In other words, there is support for queries and updates using the ADO database objects.
I've even included support for some basic SQL syntax with the help of a little SQL parser class. SQL queries like...
select * from items where name="F"
select * from items where value > "case"
update items set value="xyz" where name="A" or value="F"
...are supported; but no joins or advanced SQL syntax.
This also means that you can use it from inside a MS SQL Server 7 query using the OPENROWSET syntax.
select * from 
   OpenRowset('ServerOLEDB.ServerDb.1', '', 'select * from items')
The SQL processing is done inside the driver and not on the server, which of course is not the way to do it. It should have been placed in the application server.

Source Code Dependencies

Windows NT 4.0 SP4
Internet Information Server 5.0
Microsoft Visual C++ 6.0
Microsoft Visual Basic 6.0
Microsoft ATL Library
Microsoft MFC Library
Microsoft XML 3.0 SDK
Microsoft MDAC 2.6
Microsoft Windows SDK

Download Files

DownloadSource Code (65 Kb)

To the top