DataSnap Demo:TFDConnection、最大连接数、客户端回叫功能、多线程模拟、压力测试等...  
官方Delphi 学习QQ群: 682628230(三千人)
频道

DataSnap Demo:TFDConnection、最大连接数、客户端回叫功能、多线程模拟、压力测试等...


一、限制最大连接数,并验证来访者用户身份:


procedure TServerContainer1.DSServer1Connect(

  DSConnectEventObject: TDSConnectEventObject);

var

  sError:string;

begin

  //限制最大连接数,并且验证来访者密码

  if (DSConnectEventObject.ChannelInfo = nil)

     or (FConnections.Count > _MaxConnCount)

     or (DSConnectEventObject.ConnectProperties[TDBXPropertyNames.UserName] <> _UserName)

     or (DSConnectEventObject.ConnectProperties[TDBXPropertyNames.Password] <> _UserPassWord)

     //or (DSConnectEventObject.ChannelInfo.ClientInfo.IpAddress)<>'127.0.0.1')

     then

  begin

  try

    //客户端调用RegisterCallback或UnRegisterCallback方法时,_UserName和_UserPassWord将赋值给

    //TDBXPropertyNames.DSAuthenticationUser和TDBXPropertyNames.DSAuthenticationPassword这两个属性,

    //而真正的TDBXPropertyNames.UserName和TDBXPropertyNames.Password属性反而没有被赋值,不知道这算不算XE的一个BUG。

    //本人已修正这一“BUG”,在Datasnap.DSCommon.pas单元的第484行附近的这一函数:

    //function TDSClientCallbackChannelManager.DBXConnectionProperties(NoTimeout: Boolean): TDBXDatasnapProperties;

    //中,加上了对TDBXPropertyNames.UserName和TDBXPropertyNames.Password属性的赋值,此单元源文件我放在Demo目录下了。

    //必须加上此判断,因为注销回叫函数时会新开一个连接测试服务器是否可用,如果不加上此判断,当客户端连接数正好达到

    //我们设置的最大连接数时,因再无连接数可用会导致回叫函数一直无法被注销。

    if (DSConnectEventObject.ChannelInfo <> nil) and

       (DSConnectEventObject.ConnectProperties[TDBXPropertyNames.DSAuthenticationUser] = _UserName) and

       (DSConnectEventObject.ConnectProperties[TDBXPropertyNames.DSAuthenticationPassword] = _UserPassWord) then

       Exit;

 

    if (FConnections.Count > _MaxConnCount) then

    begin

      sError := '客户端超过服务器的最大连接数了!'

    end

    else if (DSConnectEventObject.ConnectProperties[TDBXPropertyNames.UserName]<>_UserName) or

            (DSConnectEventObject.ConnectProperties[TDBXPropertyNames.Password]<>_UserPassWord) then

      sError := '认证失败!非法的接入用户,连接被拒绝!'

    else

      sError := '';

    DSConnectEventObject.DbxConnection.Destroy;

  except

    on e:Exception do

    begin

      if sError<>'' then

        raise Exception.Create(sError)

      else

        raise e;

    end;

  end;

  end;

end;


二、最大连接数的设定

procedure TSrvMainForm.InitDSServerOpt;

begin

  _MaxConnCount := StrToIntDef(edt_MaxCount.Text,0);

  ServerContainer1.DSTCPServerTransport1.MaxThreads := _MaxConnCount+5;

  _UserName := edt_UserName.Text;

  _UserPassWord := edt_UserPwd.Text;

  //千万别设置MaxThreads属性,如果设置此属性,一旦客户端连接数超此值,服务器并不会向客户端反馈任何消息,

  //而是把客户端连接请求放入队列中,一直等到直至服务器有空闲、断开或者其他原因得到的“可用的”连接资源,

  //从而导致客户端进入假死状态。

  //ServerContainer1.DSTCPServerTransport1.MaxThreads := _MaxConnCount;

end;

三、动态注册回叫控件

procedure TClientMainForm.btn_RegCallback_DynClick(Sender: TObject);

var

  i:integer;

  se:Cardinal;

  sManagerId,sCallbackId:string;

begin

  se := GetTickCount;

  edt_SecondLength.Text := '';

  Memo1.Lines.Clear;

  Application.ProcessMessages;

 

  Screen.Cursor := crHourGlass;

  try

    FarrCount := StrToIntDef(edt_CallbackCount.Text,1);

    btn_UnRegCallback_DynClick(Self);

    SetLength(arrChannelManager,FarrCount);

 

    for i := Low(arrChannelManager) to High(arrChannelManager) do

    begin

      sCallbackId := Format('%.4d',[i+1]); //IntToStr(GetTickCount());//'XXX-LMM';

      sManagerId := '客户端_'+sCallbackId;

      if not Assigned(arrChannelManager[i]) then

        arrChannelManager[i] := TDSClientCallbackChannelManager.Create(nil)

      else

        arrChannelManager[i].UnregisterCallback(sCallbackId);

 

      arrChannelManager[i].ChannelName := 'jfglxt'; //可以把应用程序标识存放于此

      arrChannelManager[i].ManagerId := sManagerId;

      arrChannelManager[i].CommunicationProtocol := 'tcp/ip';

      arrChannelManager[i].DSHostname := edt_SrvIp.Text;

      arrChannelManager[i].DSPort := '211';

      arrChannelManager[i].UserName := edt_UserName.Text;

      arrChannelManager[i].Password := edt_UserPwd.Text;

 

      arrChannelManager[i].RegisterCallback(sCallbackId,TDemoCallback.Create);

      edt_CallbackCount.Text := IntToStr(i+1);

      Application.ProcessMessages;

    end;

  finally

    edt_SecondLength.Text := Format('%fs',[(gettickcount()-se)/1000]);

    Screen.Cursor := crDefault;

  end;

end;

四、创建多个线程,对数据库进行查询

procedure TClientMainForm.btn_RegCallback_DynClick(Sender: TObject);

var

  i:integer;

  se:Cardinal;

  sManagerId,sCallbackId:string;

begin

  se := GetTickCount;

  edt_SecondLength.Text := '';

  Memo1.Lines.Clear;

  Application.ProcessMessages;

 

  Screen.Cursor := crHourGlass;

  try

    FarrCount := StrToIntDef(edt_CallbackCount.Text,1);

    btn_UnRegCallback_DynClick(Self);

    SetLength(arrChannelManager,FarrCount);

 

    for i := Low(arrChannelManager) to High(arrChannelManager) do

    begin

      sCallbackId := Format('%.4d',[i+1]); //IntToStr(GetTickCount());//'XXX-LMM';

      sManagerId := '客户端_'+sCallbackId;

      if not Assigned(arrChannelManager[i]) then

        arrChannelManager[i] := TDSClientCallbackChannelManager.Create(nil)

      else

        arrChannelManager[i].UnregisterCallback(sCallbackId);

 

      arrChannelManager[i].ChannelName := 'jfglxt'; //可以把应用程序标识存放于此

      arrChannelManager[i].ManagerId := sManagerId;

      arrChannelManager[i].CommunicationProtocol := 'tcp/ip';

      arrChannelManager[i].DSHostname := edt_SrvIp.Text;

      arrChannelManager[i].DSPort := '211';

      arrChannelManager[i].UserName := edt_UserName.Text;

      arrChannelManager[i].Password := edt_UserPwd.Text;

 

      arrChannelManager[i].RegisterCallback(sCallbackId,TDemoCallback.Create);

      edt_CallbackCount.Text := IntToStr(i+1);

      Application.ProcessMessages;

    end;

  finally

    edt_SecondLength.Text := Format('%fs',[(gettickcount()-se)/1000]);

    Screen.Cursor := crDefault;

  end;

end;


截个图:

20150827210941235.png


20150827211009236.png



源码下载:https://download.csdn.net/download/xieyunc/9055713





转载于:https://www.cnblogs.com/xieyunc/p/4839595.html



推荐分享
图文皆来源于网络,内容仅做公益性分享,版权归原作者所有,如有侵权请告知删除!
 

Copyright © 2014 DelphiW.com 开发 源码 文档 技巧 All Rights Reserved
晋ICP备14006235号-8 晋公网安备 14108102000087号

执行时间: 0.04120397567749 seconds