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
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
这样我们就可以根据参数的配置来连接服务器
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 ;
调用代码示例
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下次打开的时候可能会报错