8月28日 ,kbmMW作者发布了文章,宣布即将到来的kbmMW新版本,将支持WebSocket!这是一个令人兴奋的消息!这样,我们就可以基于kbmMW,开发支持WebSocket的Web服务器了!

开发一个这样的服务器,将是一件简单的事件,看代码:

constructor TForm6.Create(Owner:TComponent);
begin
inherited Create(Owner);
FServer:=TkbmMWServer.Create(nil);
FTransport:=TkbmMWWebSocketServerTransport.Create(nil);
FTransport.Server:=FServer;
FTransport.OnWebSocketData:=DoOnWebSocketData;
FTransport.OnWebSocketOpen:=DoOnWebSocketOpen;
FTransport.OnWebSocketClose:=DoOnWebSocketClose;
FTransport.OnWebSocketPong:=DoOnWebSocketPong;
FServer.AutoRegisterServices;
Log.OutputToStrings(mLog.Lines);
end;

新版提供了TkbmMWWebSocketServerTransport,直接在服务端建立TkbmMWWebSocketServerTransport,并实现他的四个事件,然后再设置他的一些属性:

procedure TForm6.btnListenClick(Sender: TObject);
begin
if FServer.Active then
begin
FServer.Active:=false;
btnListen.Caption:='Listen';
end
else
begin
FTransport.Host:='0.0.0.0';
if chbUseSSL.Checked then
begin
FTransport.UseSSL:=true;
FTransport.Port:=443;
FTransport.SetSSLCertificateFromFile('.\domain.crt');
FTransport.SetSSLPrivateKeyFromFile('.\domain.key');
end
else
begin
FTransport.UseSSL:=false;
FTransport.Port:=80;
end;
FServer.Active:=true;
btnListen.Caption:='Dont listen';
end;
end;

四个事件的代码:

procedure TForm6.DoOnWebSocketData(const AConnection:IkbmMWWebSocketConnection; const AData:TValue);
var
s:string;
begin
s:=AData.ToString;
Log.Info('Got data:'+s);
AConnection.BroadcastText(s);
end;

procedure TForm6.DoOnWebSocketPong(const AConnection:IkbmMWWebSocketConnection; const AData:TValue);
begin
Log.Info('Got pong from:'+
AConnection.GetPeerAddr+':'+inttostr(AConnection.GetPeerPort)+
' : '+AData.ToString);
end;

procedure TForm6.DoOnWebSocketOpen(const AConnection:IkbmMWWebSocketConnection);
begin
AConnection.TagString:='TAG1';
Log.Info('Opening websocket connection: '+
AConnection.GetPeerAddr+':'+inttostr(AConnection.GetPeerPort)+
' now tagged as '+AConnection.TagString);
end;

procedure TForm6.DoOnWebSocketClose(const AConnection:IkbmMWWebSocketConnection; const ACode:word; const AReason:string);
begin
Log.Info('Closing websocket connection: '+
AConnection.GetPeerAddr+':'+inttostr(AConnection.GetPeerPort)+
' Code:'+inttostr(ACode)+' Reason:'+AReason);
end;

再利用kbmMW向导,建立一个Smart Web Service:

unit uHTTPService;

// =========================================================================
// kbmMW - An advanced and extendable middleware framework.
// by Components4Developers (http://www.components4developers.com)
//
// Service generated by kbmMW service wizard.
//
// INSTRUCTIONS FOR REGISTRATION/USAGE
// -----------------------------------
// Please update the uses clause of the datamodule/form the TkbmMWServer is placed on by adding services unit name
// to it. Eg.
//
// uses ...,kbmMWServer,YourServiceUnitName;
//
// Somewhere in your application, make sure to register the serviceclass to the TkbmMWServer instance.
// This can be done by registering the traditional way, or by using auto registration.
//
// Traditional registration
// ------------------------
// var
// sd:TkbmMWCustomServiceDefinition;
// ..
// sd:=kbmMWServer1.RegisterService(yourserviceclassname,false);
//
// Set the last parameter to true if this is the default service.
//
//
// Auto registration
// -----------------
// Make sure that your service class is tagged with the [kbmMW_Service] attribute.
// Then auto register all tagged services:
// ..
// kbmMWServer1.AutoRegisterServices;
//
// -----------------------------------------------
//
// SPECIFIC HTTP SERVICE REGISTRATION INSTRUCTIONS
// -----------------------------------------------
// Cast the returned service definition object (sd) to a TkbmMWHTTPServiceDefinition. eg:
//
// var
// httpsd:TkbmMWHTTPServiceDefinition;
// ..
// httpsd:=TkbmMWHTTPServiceDefinition(sd)
// httpsd.RootPath[mwhfcHTML]:='.';
// httpsd.RootPath[mwhfcImage]:='.';
// httpsd.RootPath[mwhfcJavascript]:='.';
// httpsd.RootPath[mwhfcStyleSheet]:='.';
// httpsd.RootPath[mwhfcOther]:='.';
// -----------------------------------------------



{$I kbmMW.inc}

interface

uses
SysUtils,
{$ifdef LEVEL6}
Variants,
{$else}
Forms,
{$endif}
Classes,
kbmMWSecurity,
kbmMWServer,
kbmMWServiceUtils,
kbmMWHTTPStdTransStream,
kbmMWGlobal,
kbmMWCustomHTTPSmartService
,kbmMWRTTI
,kbmMWSmartServiceUtils;

type

[kbmMW_Service('flags:[listed]')]
[kbmMW_Rest('path:/')]
// Access to the service can be limited using the [kbmMW_Auth..] attribute.
// [kbmMW_Auth('role:[SomeRole,SomeOtherRole], grant:true')]

TWebSocketService = class(TkbmMWCustomHTTPSmartService)
function kbmMWCustomHTTPSmartServiceUpgrade(Sender: TObject;
const ARequestHelper, AResponseHelper: TkbmMWHTTPTransportStreamHelper;
const ARequestedProtocols: string;
var AAcceptedProtocol: string): Boolean;
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
// HelloWorld function callable from both a regular client,
// due to the optional [kbmMW_Method] attribute,
// and from a REST client due to the optional [kbmMW_Rest] attribute.
// The access path to the function from a REST client (like a browser)+
// is in this case relative to the services path.
// In this example: http://...//helloworld
// Access to the function can be limited using the [kbmMW_Auth..] attribute.
// [kbmMW_Auth('role:[SomeRole,SomeOtherRole], grant:true')]
[kbmMW_Rest('method:get, path:helloworld')]
[kbmMW_Method]
function HelloWorld:string;
end;

implementation

uses kbmMWExceptions, uMain;

{$R *.dfm}


// Service definitions.
//---------------------

function TWebSocketService.HelloWorld:string;
begin
Result:='Hello world';
end;

function TWebSocketService.kbmMWCustomHTTPSmartServiceUpgrade(Sender: TObject;
const ARequestHelper, AResponseHelper: TkbmMWHTTPTransportStreamHelper;
const ARequestedProtocols: string; var AAcceptedProtocol: string): Boolean;
begin
AAcceptedProtocol:='websocket';
Result:=true;
end;

initialization
TkbmMWRTTI.EnableRTTI(TWebSocketService);
end.

OK,服务端就完成了!