Creating a server application can be difficult and painful for many developers even when mastering many notions of internet communication.
For this reason, I developed a project called the "Server Wizard". We all use Wizards to start our software projects. This one will guide you in many details and then create all the files needed to get a working C++ project in the same way you use the MFC project wizard for example, and get a complete application skeleton.
The server project you obtain is ready to be compiled, optionally installed as a service, and also ran and be tested using a demo client application built for this purpose.
Finally this work depends on two libraries:
- Push Framework : a library easing the creation of high performance TCP servers.
- Google Protobuf : a data serialization library that is fast and produces small streams.
The Wizard will collect their path and produce a project that links to them, generating all the code that meets the options you select.
Installation and dependencies
First thing you should do is install this Wizard into your Visual Studio instance. Let's do it for Visual Studio 2008 :
- Grab the ServerWizard.zip, unzip it into folder "Server Wizard"
- Alternatively, get the latest version from this SVN link.
- Cut and Paste the "Server Wizard" directory into: [VSInstallDir]\VC\VCWizards where VSInstallDir is the installation directory for your Visual Studio 2008 (example in my machine: "C:\Program Files (x86)\Microsoft Visual Studio 9.0"). Also, copy both Server Wizard.ico and Server Wizard.vsz into [VSInstallDir]\VC\vcprojects. You find these two files in the "Server Wizard" directory.
- Close VS2008 and reopen it. You should now see a new C++ wizard called "Server Wizard" in the "Create Project" dialog.
- Click to create a new project. Let's call it Project1.
- On the first page, Overview, the Wizard is already asking you for the path to both Push Framework and Google Protobuf:
Push Framework can be obtained from this location : http://www.pushframework.com. You should point the Wizard to the code root directory where you can find the subdirectories : include, private and the project file PushFramework.vcproj.
Also, you should build this library. It will output its .lib and .dll modules in the directory called output, outside the root directory of the source code, But please change that to either Debug/Release direcory like it is the case for any newly created project.
Concerning Google Protobuf, you can obtain it from this web place : http://code.google.com/p/protobuf/. Download and build. Now, point the wizard to the root directory in which you can see the makefiles and vsprojects sub-directory.
Walking through the Wizard
Let's go to the second page, General.
- Server class name : choose a class name for your subclass of PushFramework::Server. An instance of this object will encapsulate many functionalities.
- Server description: add a descriptive text here.
Go on to the Connections page:
- Listening port: your clients will need to connect atthis port number.
- Client class name: this will be used as the name for the subclass of PushFramework::LogicalConnection. This represents the structure where you can put data related to a logged client.
- Client Factory class name : used for the subclass of PushFramework::ClientFactory where we will be overriding many members to provide for specific behaviors.
- Maximum number of simultaneous client.
- Maximum login duration: when a connection is accepted, it is still a physical connection until a first message is received in which you decide to accept the connection as a legitimate client, ie a logical connection.
- Maximum inactivity duration. If no data is received from a logical connection for a period beyond this one, the connection will be forcibly closed.
- Challenge connections before receiving data. This will give you the chance to force sending a message to a newly accepted connection before starting to receive any incoming request. This is used to allow for sophisticated authentication mechanisms.
- Override all virtual methods of ClientFactory : the Wizard will override methods such as onClientConnected, onClientDisconnected, so you are able to put specific treatment.
The protocol page has nothing to be edited. In the beginning, I was thinking about not forcing a specific protocol, then also had the idea to offer multiple protocol implementations. Finally and for the purpose of making something concrete and testable, the choice was made on Protobuf and you can examine the generated files to see how the protocol deals with protobuf::Message objects, serializes them, then adds some header with prefix and puts the stream into the target buffer.
If your server requires broadcasting data in real time, then you will find the "Broadcast" page useful. Please resort to http://www.pushframework.com for many material about this feature.
- Count of threads. This is the number of threads to be spawned to stream broadcast messages to their subscribers (logical connections).
- Broadcast queue name : put the name of the example queue to be created.
- Size : the maximum size for the queue. A message Size + 1 pushed into the queue will cause the message 1 to be removed.
- Priority and Quota : these are Quality of Service (QoS) attributes better explained in this concrete example : http://www.pushframework.com/?page_id=435
- Force explicit registration. If checked that means every logical connection in the server will be automatically subscribed to the content of the queue.
- Ignore previous messages and throttling attributes. Please find details in Push Framework support materials.
According to Push Framework, we need to create many Service sub classes to handle clients requests. each Service will deal with a category of request and provide for a custom treatment. Checking all 3 options, will generate code that handles different types of communication workflows:
- handle client request by sending back a response
- handle client request by sending a directed response to another connected client
- handle client request by broadcasting a response to many clients through the use of broadcast queue
The Remote Monitoring options are essentials if you'd like to monitor the activity of your server remotely. See the Analytics section of Push Framework website : http://www.pushframework.com/?page_id=919
Finally, if you want to deploy your server in form of a Windows service that can be started automatically upon system start-up, then this can be done automatically for you:
Compiling and Testing your server
After the project has been generated. You should be able to successfully compile and run the server. Push Framework is a dynamic library, so PushFramework.dll must be deployed next to your executable.
If you have checked the option "register as a Windows service", then to start your server interactively, you need to add the 'm' command line. The reason is, by default the server will think it is being launched by the Services Manager (SCM) so it will communicate its entry point with it and wait for it, rather than doing actual processing.
To install the server, execute your application using the 'i' command line.
When the server is started, it should start listening for new connections. Grab the DemoClient.zip package and use the application inside to connect and test the server.
Putting your custom code
After giving an overlook to the generated code and having tested it, I'm expecting you to start adding your custom features. Here are some guidelines.
- First thing, try to foresee all exchanges possible between your server and client. Materialize those exchanges in form of messages. Describe these messages in the proto file provided. This is a langage created by Google for structured data representation. Launch the BATCH file in order to compile them unto C++ classes. Now, you have C++ classes that represent either requests coming from the client or responses to be sent to it. The Protobuf compiler also generates getters/setters for all members you add.
- Now, similar to the content of services.h .cpp, add new Service subclasses, and put custom code in the handle method. Do not forget to 'register' your Service classes using PushFramework::Server::registerService, associating them with corresponding types of Protobuf messages. So now each time, you get a request of type X, that will go to a Service subclass Y. Hence organize your logic and if you want you can separate evry new Service class into its separate files.
More help and guides
As already told, please try to get the latest sources from the Push Framework repository for both the Push Framework library and this Server Wizard project. Also you might be interested to keep up to date with Protobuf, as Google may add many essential features like the ability to add maps and other collections within messages.
For bugs or enhancements requests, please put that in the Issuer Tracker. I also offer professional development and consultancy if you need extensive help on some concrete project.