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 ...
随机推荐
- SQL Server 2012数据导入SQL Server 2008
SQL Server 2012可以降级到2008吗?没有找到方法,似乎也不支持.整理了一个变通的方法,把2012的数据和结构导出,然后再导入2008. 在 SQL Server 2012 使用 Sql ...
- gitlab备份与恢复操作方法
github私有仓库是收费的,有些代码不方便托管到外面的git仓库,因此就产生了自己搭建git服务器的需求. 好在有广大的开源人士的贡献,有了gitlab这一神器. 手动配置较多,直接用集成包: bi ...
- MySQL5.6 linux源码安装
安装mysql 创建mysql数据目录 mkdir -p /usr/local/mysql --安装目录 mkdir -p /mysql/data ---数据目录 mkdir -p /mysql/lo ...
- 属性声明(property declarations), 自定义属性,自动生成 get 和 set 方法,getter 和 setter
属性声明(property declarations), 自定义属性,自动生成 get 和 set 方法,getter 和 setter 一.普通的get 和set 属性. 一般的get 和set 属 ...
- Android 自学之列表视图ListView和ListActivity
ListView是手机系统中使用非常广泛的一种组件,它以垂直列表的形式显示所有列表项. 创建ListView有两种方式: 直接使用ListView创建. 让Activity继承ListActivity ...
- Simple Arithmetics
def Add(a, b): l = [] alen = len(a) blen = len(b) result = str(int(a) + int(b)) relen = len(result) ...
- [改善Java代码]不要让类型默默转换
建议23:不要让类型默默转换 public class Client { // 光速是30万公里/秒,常量 public static final int LIGHT_SPEED = 30 * 100 ...
- Linux下进程的创建
这篇文章主要是讲解到Linux进程的控制,包括程序和进程.守护进程.守护进程的出错处理. 1.程序和进程 程序(program)是存放在磁盘文件中的可执行文件,程序的执行实例被称为进程(process ...
- Windows 8.1 归档 —— Step 1 选择与安装
下面是 Windows 8.1 各版本区别: Windows 8.1 标准版(一般就称之为Windows 8.1): 包括全新的 Windows 商店.Windows 资源管理器.任务管理器等等,还将 ...
- asp.net上传大文件
Asp.net默认允许上传文件的最大值为4M. 如果想要上传更大的文件,需要修改web.config文件,方法是: 在<system.web>节点中添加代码 <httpRuntime ...