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/
没有评论:
发表评论