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