All along, delphi’s network communication layer is mainly indy, although indy has a lot of functions, involving network services.
In all respects, but for most multi-tier services, a fast, stable, and efficient transport layer is needed. Delphi’s datasnap
Mainly through three kinds of data communication, one is the indy that everyone hates, the other is through the isip of iis, the last one is through
Apache’s Dynamic Module (DSO) is implemented.
There are a lot of problems with indy. Basically, everyone tends to use the latter two methods. The trouble of the latter two methods is that you must install IIS or
Apache. It is also too convenient to configure a lot of things.
Fortunately, Microsoft uses http.sys as the core of web services after Windows Vista (server 2008), and IIS also passes this core.
Implement its web services. What are the advantages of using http.sys?
1. Don’t do extra coding, directly support https (Mom no longer have to worry about https)
2. Kernel-level buffering and kernel-level request queues (significantly reducing the pressure on the application server itself)
3. Multiple applications can use the same port (the firewall is very gratifying)
4. Kernel-level SSL support
5. Kernel-level static file output support
6. In theory, this is the fastest http service under Windows, no one.
With so many benefits, can we use http.sys directly in delphi to make Delphi’s multi-tier service fly under Windows?
The answer is yes, delphi can use the http.sys service very smoothly, not only webbroke, datasanp, including our commonly used kbmmw.
At present, there are two main types of third-party controls in Delphi that support http.sys. One is the famous control company TMS, which has a control called TMS Sparkle.
The main thing is to encapsulate the http.sys service. The other multi-layer controls of this company are built on this control. The only bad thing is that it is commercial software and needs
Paid to buy. The other is the famous open source framework mormot. The author’s skill is already dinosaur-class, and can enter the top ten of the delphi world. He is in mormot
It also encapsulates http.sys. Because it is open source, it is necessary to take out the corresponding package code to achieve the multi-layer application adaptation with Delphi.
Let’s take the THttpApiServer packaged by mormot as an example to illustrate how to use http.sys in a multi-tier application.
We first solve how to use THttpApiServer in webbroker?
In fact, if you know more about webbroker, you know that webbroker works by distributing the request from the client to the webbroker.
Then the response is returned to the client. Then we need to do a winapiWebBrokerBridge, the function is to complete the above requirements.
First download the mormot source and add the relevant directory.
Then join our unit, the relevant objects that need to be used are declared as follows:

unit winapiWebBrokerBridge;
interface uses   Classes,
  HTTPApp,
  SysUtils,
  system.NetEncoding,
  SynCommons,
  SynZip,
  SynCrtSock ,

  WebBroker, WebReq;type   EWBBException = class(EWebBrokerException);
  EWBBInvalidIdxGetDateVariable = class(EWBBException);
  EWBBInvalidIdxSetDateVariable = class(EWBBException );
  EWBBInvalidIdxGetIntVariable = class(EWBBException );
  EWBBInvalidIdxSetIntVariable = class(EWBBException );
  EWBBInvalidIdxGetStrVariable = class(EWBBException);
  EWBBInvalidIdxSetStringVar = class(EWBBException);
  EWBBInvalidStringVar = class(EWBBException);


 Twinapirequestinfo=class(Tobject)
 protected    FHttpServerRequest:THttpServerRequest;
   Finrawheaders:Tstringlist;
   FContentStream : TStream;
   FFreeContentStream : Boolean;
   Fhost:string;
   Fport:string;
   Fcontent:string;
   FURL:string;
   Fremoteip:string;
   Fcontentlength:integer;
   fInContentType:string;

   Fcommand:string;
 public     constructor Create(C: THttpServerRequest);
    destructor Destroy; override;
 end;

 Twinapiresponseinfo=class(Tobject)
  protected    FHttpServerRequest:THttpServerRequest;
   Foutrawheaders:Tstringlist;
   FContentStream : TStream;
   FFreeContentStream : Boolean;
   Fhost:string;
   Fport:string;
   Fcontent:string;
   Fcontenttype:string;
   Fcontentlength:integer;
   Fstatuscode:integer;
   FCookies: TCookieCollection;
 public     constructor Create(C: THttpServerRequest);
    destructor Destroy; override;
    procedure AddCookiestohead;
 end;



 TwinapiAppRequest = class(TWebRequest)
  protected     FRequestInfo   : TwinapiRequestInfo;
    FResponseInfo  : TwinapiResponseInfo;
      FFreeContentStream : Boolean;
    FStatusCode:integer;
    //    function GetDateVariable(Index: Integer): TDateTime; override;
    function GetIntegerVariable(Index: Integer): Integer; override;
    function GetStringVariable(Index: Integer): string; override;
    function GetRemoteIP: string; override;
    function GetRawPathInfo:string; override;
    function GetRawContent: TBytes; override;

  public     constructor Create(arequestinfo:Twinapirequestinfo; aresponseinfo:Twinapiresponseinfo);
    destructor Destroy; override;
    function GetFieldByName(const Name: string): string; override;

    function ReadClient(var Buffer; Count: Integer): Integer; override;
    function ReadString(Count: Integer):string; override;
     function TranslateURI(const URI: string): string; override;

    function WriteHeaders(StatusCode: Integer; const ReasonString, Headers: string): Boolean; override;

  end;

  TwinapiAppResponse = class(TWebResponse)
  protected      FRequestInfo   : TwinapiRequestInfo;
    FResponseInfo  : TwinapiResponseInfo;
   function GetContent: string; override;
     function GetStatusCode: Integer; override;
     procedure SetContent(const AValue: string); override;
    procedure SetContentStream(AValue: TStream); override;
    procedure SetStatusCode(AValue: Integer); override;
    procedure SetStringVariable(Index: Integer; const Value:string); override;
    procedure SetDateVariable(Index: Integer; const Value: TDateTime); override;
    procedure SetIntegerVariable(Index: Integer; Value: Integer); override;

  public     constructor  Create(AHTTPRequest: TWebRequest;arequestinfo:Twinapirequestinfo; aresponseinfo:Twinapiresponseinfo);
     destructor Destroy; override;
    procedure SendRedirect(const URI: string); override;
    procedure SendResponse; override;
    procedure SendStream(AStream: TStream); override;
    function Sent: Boolean; override;
  end;

  TwinapiWebBrokerBridge = class(THttpApiServer)
  private    // procedure RunWebModuleClass(C : THttpServerRequest);   protected     FWebModuleClass: TComponentClass;
   function Request(C : THttpServerRequest): cardinal;override;

  public     procedure RegisterWebModuleClass(AClass: TComponentClass);

  end;

Then we can use this to implement our webbroker application.

We started using delphi’s own wizard to build a webserver.

Ok,continue

Click to finish.

Generate the corresponding project file, then we replace the code of the main form.

The code corresponding to the main program is very simple.

unit mainp;

interface

uses
  Winapi.Messages, System.SysUtils, System.Variants,  SynCrtSock,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.AppEvnts, Vcl.StdCtrls, winapiWebBrokerBridge, Web.HTTPApp;

type
  TForm1 = class(TForm)
    ButtonStart: TButton;
    ButtonStop: TButton;
    EditPort: TEdit;
    Label1: TLabel;
    ApplicationEvents1: TApplicationEvents;
    ButtonOpenBrowser: TButton;
    procedure ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
    procedure ButtonStartClick(Sender: TObject);
    procedure ButtonStopClick(Sender: TObject);
    procedure ButtonOpenBrowserClick(Sender: TObject);
  private
    FServer: TwinapiWebBrokerBridge;
    procedure StartServer;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  WinApi.Windows, Winapi.ShellApi;
procedure TForm1.ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);begin   if fserver=nil then     begin         ButtonStart.Enabled :=True;
         ButtonStop.Enabled :=false;
         EditPort.Enabled := True;
    end     else       begin          ButtonStart.Enabled := not FServer.Started;
         ButtonStop.Enabled := FServer.Started ;
         EditPort.Enabled := not FServer.Started;
      end;end;procedure TForm1.ButtonOpenBrowserClick(Sender: TObject);var   LURL: string;begin   LURL := Format('http://localhost:%s', [EditPort.Text]);
  ShellExecute(0,
        nil,
        PChar(LURL), nil, nil, SW_SHOWNOACTIVATE);end;procedure TForm1.ButtonStartClick(Sender: TObject);begin   StartServer;end;procedure TForm1.ButtonStopClick(Sender: TObject);begin    freeandnil( FServer);end;procedure TForm1.StartServer;begin   FServer := TwinapiWebBrokerBridge.Create(True);    Fserver.Clone(10);// 开始10个进程   Fserver.AddUrl('/','8080',false,'+',true);
  fserver.Start;
end;

The webmodel is very simple.
procedure TWebModule1.WebModule1DefaultHandlerAction(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin      
response.Content:='hello!' 
end;
Then we started running this program.


Open your browser and you'll see that our webbroker program is working fine.

The webbroker server is successful, so the usual webservice is no exception.

According to the wizard that comes with it, replace the file of the corresponding main main form, run it, and stick it.

Is this really a service provided by http.sys?

Then there is a picture with the truth:

The datasnap example is no longer demonstrated, and the method is similar to the above.

 

Finally, for students who don’t use datasnap and use kbmmw, don’t worry, you can still use http.sys in kbmmw.

It is just to write the corresponding transport. The object declarations for the server and client are given below.


unit kbmMWHTTPAPIServerTransport;{$define httpsyslog} interface uses   Classes, Sysutils,
  kbmMWCustomTransport,kbmMWServer,kbmMWGlobal, variants, kbmMWHTTPUtils,
   {$ifdef httpsyslog}        kbmMWLog,
  {$endif}   SynCommons,
  SynZip,
  SynCrtSock;type   TProtServer = class(TkbmMWServer);
  TxalionTransport=class(TkbmMWCustomServerTransport);

  Txalioninfo=class(TkbmMWServerTransportInfo);


  Txalionserver = class   private          FServer:Tkbmmwserver;
         FTransport: TkbmMWCustomServerTransport;

         fPath: TFileName;
         fapiServer: THttpApiServer;
      function Process(C : THttpServerRequest): cardinal;
  public   
    destructor Destroy; override;


  end;

  TkbmMWCustomhttpapiServerTransport = class(TkbmMWCustomServerTransport)
  private     { Private declarations }       FhttpsysServer: TxalionServer;

      Fhost:string;
      Fport:string;
      FServerUrl:string;
      Fssl:boolean;
      Fversion:string;
      FHTTPQueueLength: integer;

      FServerThreadPoolCount :integer;

  public     // @exclude     constructor Create(AOwner:TComponent); override;
    // @exclude     destructor Destroy; override;

  public      class function IsSerializedTransport:boolean; override;
     class function IsConnectionlessTransport:boolean; override;

     procedure Listen; override;
     procedure Close; override;
    function IsListening:boolean; override;

    published property ServerURL:string read Fserverurl write Fserverurl;

   property Host:string read Fhost write Fhost;


    property Port:string read Fport write Fport;

    property SSL:boolean read fssl write fssl;


    Property Version:string read Fversion;
      property HTTPQueueLength: integer read FHTTPQueueLength write FHTTPQueueLength;
       property ServerThreadPoolCount: integer read FServerThreadPoolCount write FServerThreadPoolCount;

  end;

  TkbmMWhttpapiServerTransport= class(TkbmMWCustomhttpapiServerTransport)
  published     { Published declarations }     property Crypt;
    property Compression;
    property StreamFormat;
    property VerifyTransfer;
    property TransportStateOptions;
    property FormatSettings;
    property Plugin;
    property Params;
    property StringConversion;
    property NodeID;
    property ClusterID;
  end;
 {$I httpsysversion.inc}
unit kbmMWNativeHTTPClientTransport;
interface
 {$I kbmMW.inc} {.$define indyhttp} {.$define httpsyslog} uses   Classes, Sysutils, kbmMWCustomTransport,kbmMWClient,

  {$ifdef indyhttp}     idhttp,
  {$else}      System.Net.HttpClientComponent,System.Net.HttpClient,
  {$endif}   {$ifdef httpsyslog}        kbmMWLog,
  {$endif}   kbmMWGlobal;type {$IFDEF LEVEL16}   [ComponentPlatformsAttribute({$IFDEF LEVEL23}pidiOSDevice64 or {$ENDIF}{$IFDEF LEVEL18}pidiOSSimulator or pidiOSDevice or {$ENDIF}{$IFDEF LEVEL19}pidAndroid or {$ENDIF}pidWin32 or pidWin64{$IFDEF LEVEL17} or pidOSX32{$ENDIF})]{$ENDIF}   TkbmMWNativeHTTPClientTransport = class(TkbmMWCustomClientTransport)
  private      {$ifdef indyhttp}         FHttpClient:Tidhttp;
    {$else}        FHttpClient:TNetHTTPClient;
    {$endif}     FTimeout:integer;
    MyRequestContent:TMemoryStream;
    fhost:string;
    fserverurl:string;
    fssl:boolean;
    Fversion:string;
    FClientType:string;    public     constructor Create(AOwner:TComponent); override;
    destructor Destroy; override;

    class function IsSerializedTransport:boolean; override;
    class function IsConnectionlessTransport:boolean; override;

    procedure Connect; override;
    procedure Disconnect; override;
    procedure Assign(ATransport:TPersistent); override;    function ReceiveStream(AInfo:IkbmMWCustomTransportInfo; const AStream:IkbmMWCustomTransportStream; ALimit:integer):boolean; override;
    procedure TransmitStream(AInfo:IkbmMWCUstomTransportInfo; const AStream:IkbmMWCustomTransportStream); override;
    published     property Host:string  read fhost write fhost;
    property ServerURL:string read fserverurl write fserverurl;
    property SSL:boolean  read fssl write fssl;
    Property ClientType:string read FClientType;
    Property  Version:string read Fversion;


    property Crypt ;
    property Compression ;
    property StreamFormat;
    property StringConversion;
    property Timeout:integer read FTimeout write FTimeout default 3000;
    property OnException;


    property OnConnectionLost;
    property OnReconnect;
    property MaxRetries;
    property MaxRetriesAlternative;
    property ConnectionString;
    property FallbackServers;
    property AutoFallback;
    property VerifyTransfer;


  end;
  {$I httpsysversion.inc}

Application servers using http.sys are much faster and more stable than using indy.

After a lot of actual projects, the effect is very good.

All in all, on Windows, using http.sys is fast, let your service fly!