Category Archives: RTC SDK

RTC HTTP Server in 199 lines of code

Open a Text Editor of your choice, copy/paste the code below and save it as “MyHttpServer.dpr”.

program MyHttpServer;

{$APPTYPE CONSOLE}

uses
  SysUtils,

  rtcTypes,
  rtcSystem,
  rtcInfo,
  rtcConn,
  rtcDataSrv,
  rtcHttpSrv;

type
// This is our self-contained HTTP Server class ...
  TMyServer=class(TObject)
  protected
    HttpSrv:TRtcHttpServer;
    DataProv:TRtcDataProvider;

  public
    constructor Create(PortNumber:String='80'; IPVer:RtcIPV=rtc_IPVDefault);
    destructor Destroy; override;

    procedure DataProv_CheckRequest(Sender: TRtcConnection);
    procedure DataProv_DataReceived(Sender: TRtcConnection);

    procedure HttpSrv_ListenStart(Sender: TRtcConnection);
    procedure HttpSrv_ListenError(Sender: TRtcConnection; E:Exception);
    procedure HttpSrv_ListenStop(Sender: TRtcConnection);
    procedure HttpSrv_RequestNotAccepted(Sender: TRtcConnection);
    end;

constructor TMyServer.Create(PortNumber:String='80'; IPVer:RtcIPV=rtc_IPVDefault);
  begin
  // Create HttpServer and DataProvider components ...
  HttpSrv:=TRtcHttpServer.Create(nil);
  DataProv:=TRtcDataProvider.Create(nil);

  // Assign Server for our Data Provider ...
  DataProv.Server:=HttpSrv;

  // Assign Data Provider Events (handles Valid Requests) ...
  DataProv.OnCheckRequest:=DataProv_CheckRequest;
  DataProv.OnDataReceived:=DataProv_DataReceived;

  // Assign Server Events (handles the rest) ...
  HttpSrv.OnRequestNotAccepted:=HttpSrv_RequestNotAccepted;
  HttpSrv.OnListenStart:=HttpSrv_ListenStart;
  HttpSrv.OnListenStop:=HttpSrv_ListenStop;
  HttpSrv.OnListenError:=HttpSrv_ListenError;

  // Configure the Server ...
  HttpSrv.ServerPort:=PortNumber;
  HttpSrv.ServerIPV:=IPVer;
  HttpSrv.MultiThreaded:=True;

  // Start the Server listener ...
  HttpSrv.Listen();
  end;

destructor TMyServer.Destroy;
  begin
  // Stop the Server listener ...
  HttpSrv.StopListenNow();

  // Destroy the components ...
  HttpSrv.Free;
  DataProv.Free;
  end;

procedure TMyServer.DataProv_CheckRequest(Sender: TRtcConnection);
  begin
  // Check Request headers and "Accept" all Requests
  // we want to handle with our Data Provider ...
  with TRtcDataServer(Sender) do
    if (Request.Method='GET') and  // we only want "GET" requests
       (Request.ContentLength=0) then // ... with no content body
        if (Request.URI='/html') or
           (Request.URI='/json') or
           (Request.URI='/xml') or
           (Request.URI='/code') then
          Accept; // Accept the Request
  end;

procedure TMyServer.DataProv_DataReceived(Sender: TRtcConnection);
  var
    t:TRtcRecord;
  begin
  with TRtcDataServer(Sender) do
  // We will start processing the request only if
  // we have received the complee request content body ...
    if Request.Complete then
      if Request.URI='/html' then
        begin
        // We can use multiple "Write" calls
        // to prepare our HTML response ...
        Response.ContentType:='text/html';
        Write('<html><body>');
        Write('Your IP: '+PeerAddr+'<br>');
        Write('Your Port: '+PeerPort+'<br>');
        Write('Date & Time: <b>'+DateTimeToStr(Now)+'</b><br>');
        Write('Agent: <i>'+Request['User-Agent']+'</i><br>');
        Write('</body></html>');
        // All "Write" calls will be buffered,
        // RTC will calculate the "Content-Length" for us
        // and send the whole content body out as a single
        // Response - when we are finished with our event.
        end
      else
        begin
        // Using TRtcRecord to prepare our response Object ...
        t:=TRtcRecord.Create;
        try
          t.asText['agent']:=Request['User-Agent'];
          t.asText['ip']:=PeerAddr;
          t.asText['port']:=PeerPort;
          t.asDateTime['now']:=Now;
          if Request.URI='/json' then
            begin
            // Serialize to "JSON" ...
            Response.ContentType:='application/json';
            Write(t.toJSON);
            end
          else if Request.URI='/xml' then
            begin
            // Serialize to "XML-RPC" ...
            Response.ContentType:='text/xml';
            Write(t.toXMLrpc);
            end
          else if Request.URI='/code' then
            begin
            // Serialize to "Code" (RTC format) ...
            Response.ContentType:='text/plain';
            Write(t.toCode);
            end;
        finally
          t.Free;
          end;
        end
  end;

procedure TMyServer.HttpSrv_RequestNotAccepted(Sender: TRtcConnection);
  begin
  // Request wasn't accepted ...
  with TRtcDataServer(Sender) do
    begin
    // Send "404" status code back ...
    Response.Status(404,'Not Found');
    Response.ContentType:='text/plain';
    // Something to show in the Web Browser ...
    Write('Bad command.');
    // And ... Disconnect the Client.
    Disconnect;
    end;
  end;

procedure TMyServer.HttpSrv_ListenError(Sender: TRtcConnection; E: Exception);
  begin
  Writeln('Server Error: '+E.Message);
  end;

procedure TMyServer.HttpSrv_ListenStart(Sender: TRtcConnection);
  begin
  Writeln('Server started.');
  end;

procedure TMyServer.HttpSrv_ListenStop(Sender: TRtcConnection);
  begin
  Writeln('Server stopped.');
  end;

var
  MyServer:TMyServer;

begin
  try
    // Create and start our Server ...
    MyServer:=TMyServer.Create('80');
    try
      // Since this is a console application and our
      // Server is Multi-Threaded, we can do whatever
      // we want here. For simplicity reasons, we will
      // just use "ReadLn" to allow the Server to run
      // while we wait for the user to press <Enter>.

      Writeln('Press <Enter> to Quit ...');
      ReadLn;

      // User has pressed <Enter> - time to kill our Server.
    finally
      MyServer.Free;
      end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Continue reading

Accessing Databases (Main Article)

This demo will be divided in a Server and a Client.

Basically, we are going to be serving several queries to the clients from a server. To accomplish this, we will be using a database created with SQLite. SQLite is an awesome SQL Server embedded that can be easily used in Delphi. To make the connection to the database we are going to use ZeosDB components, they are open source and stable. For all the communication, of course, we will be using RTC SDK components.

So, let’s go ahead. Choose your destiny:

  1. The Server.
  2. The Client.

Accessing Databases (Server side)

The Server.

This demo will show how really simple is to create a server that can send the content of tables in a database to a client.

Steps.

  1. Create a new project in Delphi 7
  2. Create a DataModule to connect to Database and send responses back to the client
  3. Create a Form to control the Server.
  4. Compile and run the Server. Continue reading

Accessing Databases (Client side)

The Client

This is the article for the client in the Accessing Databases article. At this moment, we have our Server ready, so now it’s time to create the Client that will ask for the data. In this case, this client is really simple, in fact, as simple as it could be. This Client will call a function on the Server and get back the content of the table tbl_products in our Server’s database.

Steps.

  1. Create a form for the Client with the needed components.
  2. Write the code to  call the Remote Function. Continue reading

Write your first Remote Function (Lesson 5)

In this lesson, we’ll be building a solution with a Server and a Client. This first lesson with a Client side made with RealThinClient Components is simple but shows the concept behind a client – server system that could be the base for a larger application. We’ll be using Remote Functions to accomplish this task.

This Post has three sections.

  1. The Server.
  2. The Client.
  3. Make it work.

Continue reading

Send large files from a Server (Lesson 4)

This demo continues over Demo 3 (Sending small files). Now, we are going to make a webserver that is able to send files no matter their size.

We must be careful with our server’s memory, we may have a really big file in our server and we don’t want to use all of it.

At our first two examples we have been sending all of our content at once on the OnCheckRequest and OnDataReceived events of our RtcDataProvider components.

Continue reading

Send small files from a Server (Lesson 3)

By this moment, we have been sending content generated by our Server. Now we are going to see how to send small files from a folder that resides inside our Server’s running directory. We’ll do it this way because with this approach we can control what files can be accessed from the Server.

We’ll use some functions to secure our Server and check that the content (file size in this case) is small enough to send.

In the next lesson we’ll see how to deal with bigger file sizes.

We’ll need the code of our Lesson 2b post which you can download at Code For RealThinClient SDK Lesson 2b. Continue reading

Server using Query parameters (Lesson 2b)

Now that we have seen how to Create a Web Server and how to Send Dynamically Generated Content, we are going to see how to accept Query Parameters.

We are going to make some small changes to our previous code (Code for Demo Sending Dynamically Generated Content) to accept request’s query parameters.

When we coded our Dynamically Generated Content we give no option to the user to decide what Square values the system will return, so now, we are going to give the user the choice to:

  1. Select the starting number of the Square values.
  2. Select the ending number of the Square values.

Continue reading

Server sending dynamically generated content (Lesson 2)

Now we’re going to create an application to send Dynamically Generated Content. We’ll use as base the RealThinClient SDK – Your First Web Server  project. You can download the source code to work with.

In this lesson, you’ll see how two data providers can work together and how you can use multiple Write calls to send complex content out. Continue reading