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 ...
随机推荐
- AT-PagerAdapter
关于PagerAdapter的粗略翻译 英文版api地址:PagerAdapter(自备梯子) PagerAdapter 已知直接子类:FragmentPagerAdapter.Fra ...
- 使用markdown及highlight
一.markdown 安装markdown2 pip install markdown2 应用markdown2 进入blog APP,创建templatetags文件夹,在文件夹内创建__init_ ...
- 【思路、优化】UVa 11491 - Erasing and Winning
Juliano is a fan of the TV show Erasing and Winning, where participants are selected in a draw and r ...
- 【推理,贪心】UVa 1319 - Maximum
看到了大神的代码.理解了好久...真是差距. 题意:给出m, p, a, b,然后xi满足已下两个公式, 求 xp1 + xp2 +...+ xpm 的最大值. 1.-1/sqrt(a) <= ...
- poj 2724 二分图最大匹配
题意: 会给出M个串,我们要做的就是将这M个串给清除了.对于任意两个串,若二进制形式只有一位不一样,那么这两个串可以在一次操作消除,否则每个操作只能消除一个串. 3 3 *01 100 011 可以代 ...
- 在windows2003系统上安装两个版本的oracle
想试试oracle11g都有什么变化,于是在机器上又安装了oracle11.1.7版本的.安装很简单,只是安装后如何让两个数据库同时跑起来,需要稍微设置下.1.将11goracle的监听换一个端口,比 ...
- java-分页之页面分页
import java.util.ArrayList; import java.util.List; /** * * @author cheney * * @date Aug 31, 2012 */ ...
- mdeditor
*在线地址:* http://ghosertblog.github.io/mdeditor/ # Markdown 语法简明手册 ### 1. 使用 * 和 ** 表示斜体和粗体 示例: 这是 *斜体 ...
- html5 js os build
1.NodeJS6.6 install https://nodejs.org/en/ c:\nodejs>npm install -g grunt-cliC:\Users\police\Ap ...
- AngularJS Tabular Data with Edit/Update/Delete
效果 首先,我们先建立一些数据,当然你可以从你任何地方读出你的数据 var app = angular.module('plunker', ['ui.bootstrap']); app.control ...