2011年10月12日星期三

datasnap的初步 关于TDSTCPServerTransport的Filters

TDSTCPServerTransport的Filter属性,可以对传递的数据进行加密,压缩,再修改等,有点注入的概念。默认情况下,Datasnap自带的ZLIB, PC1,RSA三个Filter。测试了一下,RSA只对KEY加密,PC1才对内容加密,ZLIB来做压缩,ZLIB压缩实在不咋的。并且,Filter的顺序,是依次执行的。我现在打算实现,服务器的一个Log功能,记录下来进入的数据,出去的数据,要求记录下来的数据是明文
 TTransportFilter的ProcessInput,ProcessOutput光看名字比较费解,可以这么理解ProcessInput为编码,ProcessOutput可以理解为解码

 首先给DSTCPServerTransport1的Fitlers都加上默认的3个Filter。
 上一个完整的代码
unit uLogFilter;

interface

uses
  SysUtils, DBXPlatform, DBXTransport;

type
  TLogHeadFilter = class(TTransportFilter)
  public
    constructor Create; override;
    destructor Destroy; override;
    function ProcessInput(const Data: TBytes): TBytes; override;
    function ProcessOutput(const Data: TBytes): TBytes; override; //do nothing
    function Id: UnicodeString; override;
  end;

  TLogTailFilter = class(TTransportFilter)
  public
    constructor Create; override;
    destructor Destroy; override;
    function ProcessInput(const Data: TBytes): TBytes; override; //do nothing
    function ProcessOutput(const Data: TBytes): TBytes; override;
    function Id: UnicodeString; override;
  end;

procedure AddLogFilter(Filters: TTransportFilterCollection);

implementation

uses
  CodeSiteLogging;

const
  LogFilterName_Tail = 'LogTail';
  LogFilterName_Head = 'LogHead';

procedure AddLogFilter(Filters: TTransportFilterCollection);
var
  fs: TDBXStringArray;
  i: Integer;
begin
  fs := Filters.FilterIdList;
  Filters.Clear;
  Filters.AddFilter(LogFilterName_Head);
  for i := Low(fs) to High(fs) do
  begin
    Filters.AddFilter(fs[i]);
  end;
  Filters.AddFilter(LogFilterName_Tail);
end;

constructor TLogTailFilter.Create;
begin
  inherited Create;
  //CodeSite.Send(csmBlue, 'TLogTailFilter.Create');
end;

destructor TLogTailFilter.Destroy;
begin
  //CodeSite.Send(csmBlue, 'TLogTailFilter.Destroy');
  inherited Destroy;
end;

function TLogTailFilter.ProcessInput(const Data: TBytes): TBytes;
begin
  Result := Data;
  CodeSite.Send(csmOrange, 'To Client: ' + IntToStr(Length(Data)));
end;

function TLogTailFilter.ProcessOutput(const Data: TBytes): TBytes;
begin
  Result := Data;
  CodeSite.Send(csmOrange, 'From Client: ' + IntToStr(Length(Data)),
    TEncoding.ASCII.GetString(Data));
end;

function TLogTailFilter.Id: UnicodeString;
begin
  Result := LogFilterName_Tail;
end;

{ TLogInputFilter }

constructor TLogHeadFilter.Create;
begin
  inherited;
  //CodeSite.Send(csmBlue, 'TLogHeadFilter.Create');
end;

destructor TLogHeadFilter.Destroy;
begin
  //CodeSite.Send(csmBlue, 'TLogHeadFilter.Destroy');
  inherited;
end;

function TLogHeadFilter.Id: UnicodeString;
begin
  Result := LogFilterName_Head;
end;

function TLogHeadFilter.ProcessInput(const Data: TBytes): TBytes;
begin
  Result := Data;
  CodeSite.Send(csmYellow, 'To Client: ' + IntToStr(Length(Data)),
    TEncoding.ASCII.GetString(Data));
end;

function TLogHeadFilter.ProcessOutput(const Data: TBytes): TBytes;
begin
  Result := Data;
  CodeSite.Send(csmYellow, 'From Client: ' + IntToStr(Length(Data)));
end;

initialization

TTransportFilterFactory.RegisterFilter(LogFilterName_Tail, TLogTailFilter);
TTransportFilterFactory.RegisterFilter(LogFilterName_Head, TLogHeadFilter);

finalization

TTransportFilterFactory.UnregisterFilter(LogFilterName_Tail);
TTransportFilterFactory.UnregisterFilter(LogFilterName_Head);

end.
这个unit实现了上面的功能,
数据进入服务器时,DataSnap的Reader读出时按顺序经过Filter进行解码,最后的Filter,也就是这里的TLogTailFilter的ProcessOutput出来的肯定应该是明文了,记录下来。
数据出服务器时, DataSnap的Writer写数据时,也按顺序经过Filter进行编码,刚开始的肯定是明文的,也就是TLogHeadFilter的ProcessInput了,记录下来。

要使用这个unit,只要在ServerContainerUnit1单一的OnCreate里面写入即可。如下
procedure TServerContainer1.DataModuleCreate(Sender: TObject);
begin
  AddLogFilter(DSTCPServerTransport1.Filters);
end; 

最后,上个图,看看client和服务器之间的通讯是怎样的。

为方面看,我分开了,第一次是connect,然后二次调用了EchoString。可以看出一次servermethod,有3个来回的交流(一个prepare, 一个execute,一个command_close。prepare和command_close并不是每次必须的,这里因为我是每次都创建新的TServerMethods1Client),并且交流的数据都是JSON的整列。这里也打印出了编码解码前数据长度,以及编码解码后的数据长度,如果要测试ZLIB的压缩效果,可以参考。

或许要说DSServer的OnTrace事件也可以玩,但是 OnTrace只能记录Client进Server的数据,对出去的数据TRACE不到的,很遗憾。

最后,有一些其他的现成的开源Filter可用,尤其是压缩的,去http://code.google.com/p/dsfc/

没有评论:

发表评论