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

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. CEF js调用C#封装类含注释

    /* * CEF JS调用C#组装类 * * 使用方法(CefGlue为例): * public class BrowserRenderProcessHandler : CefRenderProces ...

  2. mount: can't find cdrom in /etc /fstab or /etc/mtab

    我用的linux操作系统类别是CentOS-6.5 首先在虚拟机选项的设置里设置CD/DVD选项其中勾选Connect at power on选项 在连接中选择Use ISO image file:即 ...

  3. ubunutu_install_sublime_china

    保存下面的代码到文件sublime_imfix.c(位于~目录) #include <gtk/gtkimcontext.h> void gtk_im_context_set_client_ ...

  4. 【优先队列】【最近连STL都写不出来了/(ㄒoㄒ)/~~】hdu_5360/多校#6_1008

    题意:就是让你写出一个邀请朋友的顺序,朋友答应一起出去玩的条件是除他以外所有同意出去玩的人数要在[ l[i], r[i] ]范围内,否则他就不答应. 分析:这题比赛的时候想麻烦了,其实只要在左边界满足 ...

  5. # li鼠标移入移出,点击,变背景色,变checkbox选中状态

    移入移出背景色改变和点击背景色改变,两者是否相互覆盖? 若移出背景色恢复,影响点击事件的背景色改变,会产生效果为: 点击时,背景色改变,并且checkbox选中 鼠标移开后,checkbox仍选中,但 ...

  6. JMS - QueueBrowser

    QueueBrowser 是一个专用对象,提供提前浏览 Queue 上的排队消息的功能,而实际上并没有真正消费这些消息.这是点对点消息传送模型的独有特性.从 QueueBrowser 获得消息是该队列 ...

  7. jquery easyui datagrid 分页 详解(java)

    1.首先引入easyui包,可以在官方网站下载,http://www.jeasyui.com/download/index.php <link rel="stylesheet" ...

  8. ASP.NET网站前端页面的复制

    网络普及的时代,遇到问题的首要解决方案并不是问人,而是找度娘.当我们找一些技术性的问题时,会发现很多解决方案在博客里,看看博主发表的博客总是惊叹不已,想要自己也有这么一个好习惯,把学到的东西以自己的方 ...

  9. Java之绘制艺术图案

    前面已经介绍过绘制方法.这里不再赘述. package com.caiduping; import java.awt.Color; import java.awt.Graphics; import j ...

  10. iOS预处理指令

    预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器.可见预处理过程先于编译器对源代码进行处理. 预处理指令是以#开头的代码行,#后是指令关键字,在关键字和#号之间允许存在任意个数的空 ...