Your first Web Server (Lesson 1)

We’re going to build a Web Server with RealThinClient SDK in Delphi.

Basically we are going to:

  • Create a Project
  • Add two RealThinClient SDK components (RtcHTTPServer and RtcDataProvider)
  • Configure three events.
  • Check that our Web Server is working.

We’ll be working the code sections in two formats, one using the with clause and another without it.

Steps.

1. Create a new VCL Forms project.

In RAD Studio, go to File -> New

Create a new VCL Forms Project in Delphi

Create a new VCL Forms Project in Delphi

After this we should have a new VLC Form created.

New Project Created with a VCL Form ready to use

New Project Created with a VCL Form ready to use

2. Add a RtcHttpServer component to our Form.

We add one RtcHttpServer component from our components palette, it should be in the RTCServer group. We are using RtcHttpServer Component because we are going to create an EXE file, if we would like to go the DLL way with ISAPI, then we will use TRtcISAPIServer.

RtcHttpServer Component in the components palette

RtcHttpServer Component in the components palette

Take it and drag it to the Form1 area.

RtcHttpServer Component On Form1

RtcHttpServer Component On Form1

Now, we have our component ready to be used. We should set the port in which our server will listen for requests, Normally, all web servers listen by default on Port 80. So we will make our port listen in Port 80, unless you have another web server installed in your machine and listening in Port 80, you have to use another port.

To set the port we go to our component properties. If you have not selected the RtcHttpServer1 component, click on it and go to the properties section. If you don’t see the properties window in your screen, press F11. In the properties window we will look for a property called ServerPort and set it’s value to 80. For this example we are using just one Server listening on Port 80 but we may several Servers in the same application listening in several ports.

Server Port Property

Server Port Property

3. Make the RtcHttpServer1 component start listening when our Form is created.

Now we have to instruct our RtcHttpComponent to start listening for requests as soon as the form is created and our application started. To do this, we select our Form1 and double click on it, or, select our Form1, go to properties window, click on Events tab and then click on the OnCreate event. Delphi will create the handler for the OnCreate() event and will show it on screen.

Form Create Event

Form Create Event

We must add the code to the FormCreate event. This is because we want our RtcHttpServer to start listening for requests as soon as the application starts its execution so we don’t need any other kind of controls to start our server.

Code:

procedure TForm1.FormCreate(Sender: TObject);
begin
  RtcHttpServer1.Listen();
end;

Now, the Listen() method for the RtcHttpServer component can accept one parameter: Restarting, this by default is set to False. This parameter works in combination with RestartOn. RestartOn allows to define three properties:

  • ListenError: Set this parameter to TRUE if you want your server to restart when the service is not able to start.
  • ListenLost: Set this parameter to TRUE if you want your server to restart when the service stops listening for requests on the designated port.
  • Wait: Defines how much time the server should wait in seconds before trying to restart the service.

4. Add a RtcDataProvider to our Form.

Now that we have our server ready to listen for requests, we add one RtcDataProvider component to the form. Take a TRtcDataProvider component from the RTCServer component group and drag it to the Form1. We need a RtcDataProvider component because at this moment we have a Server that is listening for requests, but it will not know what to do if a request arrives, so, for every type of request that we would like to give an answer in our server, we have to define an RtcDataProvider.

RtcDataProvider On Palette

RtcDataProvider On Palette

Now we should have two components in our Form.

RtcDataProvider Component On Form

RtcDataProvider Component On Form

5. Set RtcDataProvider Server property to RtcHttpServer1.

We must define the Server for the RtcDataProvider1 component, in this case the Server will be RtcHttpServer1. We need to do this because we have to tell our RtcDataProvider component what Server will use in case we have other Servers (RtcHttpServer components) listening on different ports.

RtcDataProvider  Linked to the Server

RtcDataProvider Linked to the Server

Once the Server for which RtcDataProvider component will process requests is defined, we have to define which requests this component will process.

7. Define the OnCheckRequest event for our RtcDataProvider component.

To check for a request we will define the OnCheckRequest event for the RtcDataProvider component. As we said before, we can have multiple Server components listening on different ports in our applications, and every Server may have many Data Providers awaiting for requests. So the OnCheckRequest will be called once for all Data Providers linked to the Server which have received the request, until one of the Data Providers accept it.

To do this, with our RtcDataProvider component selected, we click on Events on the Properties window and then double click on the OnCheckRequest event

RtcDataProv OnCheckRequest Event

RtcDataProv OnCheckRequest Event

The code window will show us something like this

RtcDataProvider OnCheckRequestEvent Code

RtcDataProvider OnCheckRequestEvent Code

The code in this section will be like this:

Using with

procedure TForm1.RtcDataProvider1CheckRequest(Sender: TRtcConnection);
begin
  with Sender as TRtcDataServer do
    if UpperCase(Request.FileName) = '/TIME' then
      Accept;
end;

Without using with

procedure TForm1.RtcDataProvider1CheckRequest(Sender: TRtcConnection);
  var
    rdsSever : TRtcDataServer absolute Sender;
begin
  if UpperCase(rdsServer.Request.FileName) = '/TIME' then
    rdsServer.Accept;
end;

We are using Sender as TRtcDataServer so that we can compile our application as an standalone EXE or as a DLL file. TRtcDataServer is the base class for TRtcHttpServer and TRtcISAPIServer, so to keep compatibility without making any changes if we decide to go for any of the solutions (EXE or DLL), we use it this way.

Request.Filename is the complete file name requested by the client. The Request property of the RtcDataServer component can also get other data as Host name, Content Length and Type, Query parameters, HTTP headers, etc.

We are accepting request for “/TIME”. So, in this case any of the following will be processed:

  • http://localhost/time
  • http://localhost/Time
  • http://127.0.0.1/TIME

And any of it variations. Remember that we are converting to upper case the received FileName request, so it won’t matter how the client sends the request as long as it is the phrase “/time”.

8. Define the OnDataReceived event for our RtcDataProvider component.

Now, we define the OnDataReceived event for the RtcDataProvider component. Once the OnCheckRequest event has validated that the RtcDataProvider should accept the request, the OnDataReceived event is called once to accept every data package until all the content is received, so here we will define what the response should be for the received request. To do this, with our RtcDataProvider component selected, we click on Events at the Properties window and then double click on the OnDataReceived event.

RtcDataProvider OnDataReceived Event

RtcDataProvider OnDataReceived Event

The code window will show us something like this

RtcDataProvider OnDataReceived Event Code

RtcDataProvider OnDataReceived Event Code

The code in this section will look like this:

Using with

procedure TForm1.RtcDataProvider1DataReceived(Sender: TRtcConnection);
begin
  with Sender as TRtcDataServer do
    if Request.Complete then
      Write('Current Time is: ' + TimeToStr(Now));
end;

Without using with

procedure TForm1.RtcDataProvider1DataReceived(Sender: TRtcConnection);
  var
    rdsServer: TRtcDataServer absolute Sender;
begin
  if rdsServer.Request.Complete then
    rdsServer.Write('Current time is: ' + TimeToStr(Now));
end;

The purpose of the Request.Complete property of the Sender parameter is to check if we have received the complete request, because the OnCheckRequest event could be called multiple times.

Using the Read method on the Sender parameter will give us the current content of the receiver buffer, then clear the receiver buffer content. And by using the Write method, we can send our response back to the Client.

9. Compile and run the project.

Now we Compile and Run the Project. Press F9 and you will see this on the screen if there are no errors in the code

Project Running

Project Running

10. Open your web browser and go to http://localhost/time

If you selected Port 80 the you can go to http://localhost/time to check Server’s response

Browser Showing Server´s Response

Browser Showing Server´s Response

However, if you have a service already running and declared a Port other than 80 you should specify it in the browser’s address bar, something like http://localhost:81/time where 81 is the port that you assigned to your application

Browser With Different Port

Browser With Different Port

With this we conclude our first Demo for the RealThinClient SDK Components.

Files included in this post: