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

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;

截个图:

源码下载:

DataSanpDemo.rar

版权声明:本文为博主原创文章,未经博主允许不得转载。

DataSnap Demo:TFDConnection、最大连接数、客户端回叫功能、多线程模拟、压力测试等的更多相关文章

  1. 带连接池的netty客户端核心功能实现剖解

    带连接池的netty客户端核心功能实现剖析 带连接池的netty的客户端核心功能实现剖析 本文为原创,转载请注明出处 源码地址: https://github.com/zhangxianwu/ligh ...

  2. 聊天系统Demo,增加Silverlight客户端(附源码)-- ESFramework 4.0 快速上手(09)

    在ESFramework 4.0 快速上手 -- 入门Demo,一个简单的IM系统(附源码)一文中,我们介绍了使用ESFramework的Rapid引擎开发的winform聊天程序,本文我们将在之前d ...

  3. C#开发微信门户及应用(25)-微信企业号的客户端管理功能

    我们知道,微信公众号和企业号都提供了一个官方的Web后台,方便我们对微信账号的配置,以及相关数据的管理功能,对于微信企业号来说,有通讯录中的组织架构管理.标签管理.人员管理.以及消息的发送等功能,其中 ...

  4. CentOS 5.5 虚拟机安装 VirtualBox 客户端增强功能

    .启动安装在 VirtualBox 中的 CentOS 5.5 虚拟机,点击“设备” => “安装增强功能”.这个时候你就可以看到有一个“光盘”已经挂载到 CentOS 5.5 的桌面上了.它包 ...

  5. 使用tcpcopy导入线上流量进行功能和压力测试

    - 假设我们要上线一个两年内不会宕机的先进架构.在上线前,免不了单元测试,功能测试,还有使用ab,webbench等等进行压力测试. 但这些步骤非生产环境下正式用户的行为.或许你会想到灰度上线,但毕竟 ...

  6. nginx配置之状态模块和压力测试功能

    状态模块功能 nginx.conf中的http{}中的server{}中: location /status { #开启nginx状态功能 stub_status on; } 直接在网页中请求stat ...

  7. 实验一:实现求正整数1-N之间所有质数的功能,并进行测试。

    实验一 Java开发环境的熟悉(Linux + Eclipse) 实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用Eclipse 编辑.编译.运行.调试Java程序. 命令行下的程序开 ...

  8. 使用jmeter进行压力测试与nginx连接数优化

    案例训练目标 学会使用jmeter工具 学会配置nginx连接数优化 包含技能点 使用jmeter做压力测试 配置nginx的并发连接数 环境要求 PC支持VT,4G内存以上:vmware虚拟机安装有 ...

  9. DataSnap如何监控Tcp/IP客户端的连接情况

    一个实例,如果客户端是TCP/IP是短连接的情况就没有必要了. 一.GlobVar.pas单元,定义应用系统全局数据类型及变量: unit GlobVar; interface uses System ...

随机推荐

  1. 嵌入式 Linux 应用:概述

    转载:http://www.ibm.com/developerworks/cn/linux/embed/embl/overview/index.html   从腕表到基于群集的超级计算机 在对嵌入式 ...

  2. BootStrap2学习日记8---表单

    <form> <label for="username">用户名</label> <input id="username&quo ...

  3. 使用文档注释(javadoc)

    相信作为Java程序猿,几乎每个人都使用过javac,Java这样的命令吧.想想我们平时使用的Java帮助文档(API),感觉挺好用的,其实它就是使用Java中的命令javadoc做成的.下面简单介绍 ...

  4. ThreadPoolExecutor运转机制详解

    ThreadPoolExecutor运转机制详解 - 走向架构师之路 - 博客频道 - CSDN.NET 最近发现几起对ThreadPoolExecutor的误用,其中包括自己,发现都是因为没有仔细看 ...

  5. [改善Java代码]覆写equals方法时不要识别不出自己

    建议45: 覆写equals方法时不要识别不出自己 我们在写一个JavaBean时,经常会覆写equals方法,其目的是根据业务规则判断两个对象是否相等,比如我们写一个Person类,然后根据姓名判断 ...

  6. [改善Java代码] 推荐使用序列化实现对象的拷贝

    建议44: 推荐使用序列化实现对象的拷贝 上一个建议说了对象的浅拷贝问题,实现Cloneable接口就具备了拷贝能力,那我们来思考这样一个问题:如果一个项目中有大量的对象是通过拷贝生成的,那我们该如何 ...

  7. [设计模式]<<设计模式之禅>>工厂方法模式

    1 女娲造人的故事 东汉<风俗通>记录了一则神话故事:“开天辟地,未有人民,女娲搏黄土做人”,讲述的内容就是大家非常熟悉的女娲造人的故事.开天辟地之初,大地上并没有生物,只有苍茫大地,纯粹 ...

  8. VS中的波浪线

    绿色波浪线: 如果你的代码中出现了绿色的波浪线,说明你的代码语法并没有错误, 只不过提示你有可能会出现错误,但是不一定会出现错误.警告线 红色波浪线: 如果你的代码中出现了红色的波浪线,意味着你的代码 ...

  9. CSS实现标题超出宽度省略号来表示

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...

  10. Tomcat - JNDI 配置

    1. Create Your JavaBean Class Create the JavaBean class which will be instantiated each time that th ...