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;
截个图:
源码下载:
版权声明:本文为博主原创文章,未经博主允许不得转载。
DataSnap Demo:TFDConnection、最大连接数、客户端回叫功能、多线程模拟、压力测试等的更多相关文章
- 带连接池的netty客户端核心功能实现剖解
带连接池的netty客户端核心功能实现剖析 带连接池的netty的客户端核心功能实现剖析 本文为原创,转载请注明出处 源码地址: https://github.com/zhangxianwu/ligh ...
- 聊天系统Demo,增加Silverlight客户端(附源码)-- ESFramework 4.0 快速上手(09)
在ESFramework 4.0 快速上手 -- 入门Demo,一个简单的IM系统(附源码)一文中,我们介绍了使用ESFramework的Rapid引擎开发的winform聊天程序,本文我们将在之前d ...
- C#开发微信门户及应用(25)-微信企业号的客户端管理功能
我们知道,微信公众号和企业号都提供了一个官方的Web后台,方便我们对微信账号的配置,以及相关数据的管理功能,对于微信企业号来说,有通讯录中的组织架构管理.标签管理.人员管理.以及消息的发送等功能,其中 ...
- CentOS 5.5 虚拟机安装 VirtualBox 客户端增强功能
.启动安装在 VirtualBox 中的 CentOS 5.5 虚拟机,点击“设备” => “安装增强功能”.这个时候你就可以看到有一个“光盘”已经挂载到 CentOS 5.5 的桌面上了.它包 ...
- 使用tcpcopy导入线上流量进行功能和压力测试
- 假设我们要上线一个两年内不会宕机的先进架构.在上线前,免不了单元测试,功能测试,还有使用ab,webbench等等进行压力测试. 但这些步骤非生产环境下正式用户的行为.或许你会想到灰度上线,但毕竟 ...
- nginx配置之状态模块和压力测试功能
状态模块功能 nginx.conf中的http{}中的server{}中: location /status { #开启nginx状态功能 stub_status on; } 直接在网页中请求stat ...
- 实验一:实现求正整数1-N之间所有质数的功能,并进行测试。
实验一 Java开发环境的熟悉(Linux + Eclipse) 实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用Eclipse 编辑.编译.运行.调试Java程序. 命令行下的程序开 ...
- 使用jmeter进行压力测试与nginx连接数优化
案例训练目标 学会使用jmeter工具 学会配置nginx连接数优化 包含技能点 使用jmeter做压力测试 配置nginx的并发连接数 环境要求 PC支持VT,4G内存以上:vmware虚拟机安装有 ...
- DataSnap如何监控Tcp/IP客户端的连接情况
一个实例,如果客户端是TCP/IP是短连接的情况就没有必要了. 一.GlobVar.pas单元,定义应用系统全局数据类型及变量: unit GlobVar; interface uses System ...
随机推荐
- __asm__ __volatile__("": : :"memory");
参考:http://stackoverflow.com/questions/14950614/working-of-asm-volatile-memory asmvolatile("&quo ...
- c语言指针函数与函数指针
例一:指针函数 指针函数是指带指针的函数,即本质是一个函数.函数返回类型是某一类型的指针 类型标识符 *函数名(参数表) int *f(x,y); 首先它是一个函数,只不过这个函数的返回值是一个 ...
- C语言之指针与数组总结
和指针相关的问题口诀1: 1. 地址变量得地址,得谁地址指向谁 和指针相关的问题要画图: 内容变量画房子,指针画箭头 ---->口 ------------------------------- ...
- 《JavaScript学习指南》第2版 学习笔记1
1.<noscript> 标签 noscript 元素用来定义在脚本未被执行时的替代内容(文本). 注释:如果浏览器支持脚本,那么它不会显示出 noscript 元素中的文本.无法识别 & ...
- 字体的大小(pt)和像素(px)如何转换?
px:相对长度单位.像素(Pixel). pt:绝对长度单位.点(Point). 1in = 2.54cm = 25.4 mm = 72pt = 6pc 具体换算是: Points Pixels Em ...
- Objective-C ,ios,iphone开发基础:ios数据库(The SQLite Database),使用终端进行简单的数据库操作
SQLite 是一个轻量级的免费关系数据库.SQLite最初的设计目标是用于嵌入式系统,它占用资源非常少,在嵌入式设备中,只需要几百K的内存就够了,可以在(http://www.sqlite.org ...
- CF Exam (数学)
Exam time limit per test 1 second memory limit per test 256 megabytes input standard input output s ...
- 屏蔽cBox广告的方法 无需安装软件
在hosts文件中加入两句代码: 127.0.0.1 games.cntv.cn 127.0.0.1 d.cntv.cn
- less-2
样式内嵌: 生成css: 样式运算: 生成的css文件:
- HDOJ2002计算球体积
计算球体积 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...