网语飘飘.Net/Delphi攻坚战

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

DataSnap 2009的客户端采用了原始的TClientSocket组件实现了通讯层 即简单效率也不错

但是如果我们想要设置连接超时怎么办?想要设置代理服务器又该怎么办呢?能不能利用我们常用的网络控件(indy ics synapse...)来替代呢?

在这里我基于synapse控件实现了一个自己的DataSnap客户端驱动

注: synapase是一套比较不错的开源的第三方控件 这里我们要使用它的TCP控件来扩展支持代理服务器的使用

    synapse 官方网址 http://www.synapse.ararat.cz/doku.php

    synapse svn地址 https://synalist.svn.sourceforge.net/svnroot/synalist/trunk

 

首先我们必须注册一个新的驱动

// 客户端驱动定义
TCfSynaTCPDatasnapDriver 
= class
(TDBXClientDriver)
protected

  
function CreateChannel: TDbxChannel; override;
public

  
constructor Create(DriverDef: TDBXDriverDef); override;
end
;

//
 驱动名称
const SDriverName = 'CfSynaTCPDataSnap'
;

//
 单元初始化时注册驱动
initialization

  TDBXDriverRegistry.RegisterDriverClass(SDriverName, TCfSynaTCPDatasnapDriver);

 

TDBXClientDriver的CreateChannel方法默认创建的是TDBXSocketChannel 所以我们要在我们的类中覆盖它并且创建一个自己的Channel

// Synapse 实现的TCP通道
TCfSynaTCPChannel 
= class
(TDBXChannel)
private

  FTcpClient: TTCPBlockSocket; // Synapse的TCP控件
protected
  
function GetChannelInfo: TDBXChannelInfo; override;
public

  
destructor Destroy; override;
  
procedure Open; override
;
  
procedure Close; override
;
  
function Read(const Buffer: TBytes; const Offset: Integer; const Count: Integer): Integer; override
;
  
function Write(const Buffer: TBytes; const Offset: Integer; const Count: Integer): Integer; override
;
end;

 

那么我们如何读取SQLConnection设置的参数值呢 比如服务器信息 代理服务器信息之类的设置呢

为了减少代码量我在这里直接继承TDBXDatasnapProperties类实现了TCfSynaTCPDatasnapProperties类来设置代理服务器信息

// 包含代理服务器配置的属性类
TCfSynaTCPDatasnapProperties 
= class
(TDBXDatasnapProperties)
strict 
private

  
function GetProxyIP: string;
  
function GetProxyPort: string
;
  
function GetProxyUsername: string
;
  
function GetProxyPassword: string
;
  
function
 GetProxyTimeout: Integer;
  
function
 GetProxyType: TProxyType;
  
procedure SetProxyIP(const Value: string
);
  
procedure SetProxyPort(const Value: string
);
  
procedure SetProxyUsername(const Value: string
);
  
procedure SetProxyPassword(const Value: string
);
  
procedure SetProxyTimeout(const
 Value: Integer);
  
procedure SetProxyType(const
 Value: TProxyType);
published

  
property ProxyIP: string read GetProxyIP write SetProxyIP;
  
property ProxyPort: string read GetProxyPort write
 SetProxyPort;
  
property ProxyUsername: string read GetProxyUsername write
 SetProxyUsername;
  
property ProxyPassword: string read GetProxyPassword write
 SetProxyPassword;
  
property ProxyTimeout: Integer read GetProxyTimeout write
 SetProxyTimeout;
  
property ProxyType: TProxyType read GetProxyType write
 SetProxyType;
end;

然后通过TCfSynaTCPDatasnapDriver的构造函数传递

复制DbxDatasnap单元TDBXDatasnapDriver的代码 把TDBXDatasnapProperties改成TCfSynaTCPDatasnapProperties

 

这样我们就可以根据参数的配置来连接服务器

procedure TCfSynaTCPChannel.Open;
begin

  Close;
  
if FTcpClient = nil then
    FTcpClient :
= TTCPBlockSocket.Create;
  
with TCfSynaTCPDatasnapProperties(DbxProperties) do

  
begin
    
if ProxyIP <> '' then
    
begin
      
case ProxyType of
        ptSocks4:
          FTcpClient.SocksType :
= ST_Socks4;
        ptSocks5:
          FTcpClient.SocksType :
=
 ST_Socks5;
      
end
;
      
case ProxyType of

        ptSocks4, ptSocks5:
        
begin
          FTcpClient.SocksIP       :
= ProxyIP;
          FTcpClient.SocksPort     :
=
 ProxyPort;
          FTcpClient.SocksUsername :
=
 ProxyUsername;
          FTcpClient.SocksPassword :
=
 ProxyPassword;
          FTcpClient.SocksTimeout  :
=
 ProxyTimeout;
        
end
;
        ptHTTP:
        
begin

          FTcpClient.HTTPTunnelIP      :
= ProxyIP;
          FTcpClient.HTTPTunnelPort    :
=
 ProxyPort;
          FTcpClient.HTTPTunnelUser    :
=
 ProxyUsername;
          FTcpClient.HTTPTunnelPass    :
=
 ProxyPassword;
          FTcpClient.HTTPTunnelTimeout :
=
 ProxyTimeout;
        
end
;
      
end
;
    
end
;
    FTcpClient.Connect(HostName, IntToStr(Port));
  
end
;
  FChannelInfo :
= TDBXSocketChannelInfo.Create(0
, FTcpClient.GetLocalSinIP);
end;

 

调用代码示例

with DM.SQLConnection do
begin
  Close;
  Params.Values[TCfSynaTCPNames.ProxyType]     :
= IntToStr(Integer(ptHTTP));
  Params.Values[TCfSynaTCPNames.ProxyIP]       :
= 'localhost'
;
  Params.Values[TCfSynaTCPNames.ProxyPort]     :
= '80'
;
  Params.Values[TCfSynaTCPNames.ProxyUsername] :
= 'abc'
;
  Params.Values[TCfSynaTCPNames.ProxyPassword] :
= '123'
;
  Params.Values[TDBXPropertyNames.HostName]    :
= 'localhost'
;
  Params.Values[TDBXPropertyNames.Port]        :
= '1217'
;
  
try

    Open;
  
except
  
end
end;

 

单元实现完整代码 CfSynaTCPChannel.rar

注: 该单元可以直接引用也可以新建个包安装 最好在Register函数中调用InstallSynaDriver

否则IDE中SQLConnection控件的Driver设置成CfSynaTCPDataSnap下次打开的时候可能会报错

posted on 2009-11-17 23:07  网语飘飘  阅读(153)  评论(0)    收藏  举报