XE6 DataSnap 回叫功能实例(服务器、客户端)编程体会

lyhoo163 2014-05-22 02:54:48
最近,学习XE6下的DataSnap回叫技术编译代码,体会如下:

第一篇 服务器与客户端回叫

从Delphi2010开始,DataSnap支持回叫(Call Back)机制。这样,在调用耗时较长的方法时,通过回叫机制,返回服务器进程或正在处理的目标对象。

一、客户端实现步骤
在客户端声明TClientModule1的单元文件uClientModule中:
1、声明一个从TDBXCallback继承下来的对象(用于回叫参数值),并实现复载的步骤。

type
TInitCallback = class(TDBXCallback)
function Execute(const Arg: TJSONValue): TJSONValue; override;
end;

TProgCallback = class(TDBXCallback)
function Execute(const Arg: TJSONValue): TJSONValue; override;
end;

2、初始化创建该对象

Initialization // 初始化 创建
InitCallback := TInitCallback.Create;
ProgCallback := TProgCallback.Create;

3、实现声明的方法

function TProgCallback.Execute(const Arg: TJSONValue): TJSONValue;
begin
with MainFrm do
begin
ProgressBar1.Position := TJSONNumber(Arg).AsInt;
Button5.Enabled := (TJSONNumber(Arg).AsInt = ProgressBar1.Max);
end;
//刷新屏幕
Application.ProcessMessages;
Result := TJSONNull.Create; // 回传Null值
end;

function TInitCallback.Execute(const Arg: TJSONValue): TJSONValue;
begin
with MainFrm do
begin
ProgressBar1.Max := TJSONNumber(Arg).AsInt;
ProgressBar1.Step := 5;
Edit1.Text := '总时长:' + TJSONNumber(Arg).ToString + '秒';
Button5.Enabled := False;
end;
Result := TJSONNull.Create;
end;

4、调用回叫方法
procedure TMainFrm.Button5Click(Sender: TObject);
begin
ClientModule1.ServerMethods1Client.LongTimeRunFunc(InitCallback, ProgCallback);
end;

二、服务器端实现步骤
在服务器端声明TServerMethods1的单元文件uServerMethods中:
1、编写一个带回叫机制的方法
在方法的形参中,带入客户端的回叫参数:

function TServerMethods1.LongTimeRunFunc(InitCallback, ProgCallback: TDBXCallback): boolean;
var Max: Integer;
I: Integer;
begin
Max := Random(120) + 1;
InitCallback.Execute(TJSONNumber.Create(Max)).Free; // 将Max值通过JSON格式,通过InitCallback执行回叫后,释放该对象
for I := 0 to Max do
begin
ProgCallback.Execute(TJSONNumber.Create(I)).Free; // 将I值通过JSON格式,通过ProgCallback执行回叫后,释放该对象
sleep(1000);
end;
Result := True;
end;

2、声明该方法

public
{ Public declarations }
function LongTimeRunFunc(InitCallback, ProgCallback: TDBXCallback): boolean;

三、客户端声明服务器端输入方法的对象
服务器端声明的方法(对象),需要在客户端中声明,才能使得二者之间实现数据传递。
1、执行服务器端程序。
2、在客户端的ClientModule1的单元,通过鼠标右键点击SQLConnection1,选择“Generate DataSnap client classses”项目。

四、运行机制
客户端声明的TProgCallback是继承TDBXCallback的对象,它复载虚方法Execute,在服务器端运行,接受一个TJSONValue的参数,并且回传一个TJSONValue的结果值。TDBXCallback的回叫机制很有意思:服务器端在回叫客户端的方法时,可以将需要回传缎带客户端的值或对象,以TJSONValue的形式,当作虚方法Execute的参数回传缎带客户端,而客户端的方法,在被回叫执行完毕后,也可以将执行结果,以TJSONValue的形式,回传给服务器端。

...全文
2116 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
lyhoo163 2015-02-28
  • 打赏
  • 举报
回复
结贴。给分。
FlashDance 2015-01-22
  • 打赏
  • 举报
回复
InitCallback和ProgCallback不需要(无法释放)吗?即使在FormClose中释放它们,退出时也会出现内存错误。 难道是DataSnap自动管理的?
lsh341999 2014-08-01
  • 打赏
  • 举报
回复
可以的 演示 http://pan.baidu.com/s/1hqmOVgo
英年渐肥 2014-07-29
  • 打赏
  • 举报
回复
这种回叫方式是实时的,我想的实现比如qq这样的方式,发送一个消息过去就行了
FlashDance 2014-05-29
  • 打赏
  • 举报
回复
这些都不是XE6中的新特性啊,和XE3的一样。 另外问一下,服务器上能否取得客户端CallbackId、ClientId对应的socket连接。 (多个客户端注册CallbackId时可以重复,ClientId不可重复)
lyhoo163 2014-05-28
  • 打赏
  • 举报
回复
引用 5 楼 nantony 的回复:
如何实现服务器向客户端发送消息,在客户端弹出来呢
应该可以: 客户端在住留的下,当收到回叫消息后,激活(弹出来)。
hhhfff2010 2014-05-27
  • 打赏
  • 举报
回复
顶顶,鲁大湿。。。
asd杂草 2014-05-27
  • 打赏
  • 举报
回复
up,感谢楼主分享
yijitong 2014-05-27
  • 打赏
  • 举报
回复
XE6编程,DataSnap回叫功能非常有用,代码下载可运行。谢谢。
英年渐肥 2014-05-27
  • 打赏
  • 举报
回复
如何实现服务器向客户端发送消息,在客户端弹出来呢
lyhoo163 2014-05-22
  • 打赏
  • 举报
回复
上述代码均XE6 编译通过:回叫功能的服务器、客户端实例二个例子: (1)服务器与客户端之间的回叫演示 (2)服务器与客户端之间,客户端与客户端之间回叫演示。 包含学习体会,以及服务器、客户端调试方法,下载地址: http://download.csdn.net/detail/lyhoo163/7385107 欢迎批评指正。
lyhoo163 2014-05-22
  • 打赏
  • 举报
回复
第二篇 回叫信道 DataSnap XE3新增回叫信道功能。技术关键点: (1)TDBXCallback机制; (2)TDServer.BroadcastMessage方法; (3)TDSClientCallbackChanneManager1.RegisterCallback方法; 三、回叫的方式 1、服务器端回叫所有(同一信道)客户端 2、客户端回叫(同一信道)的其它客户端 3、客户端可以注册多个信道 一、服务器端对回叫信道的设置 1、服务器端回叫信道的注册 编程时,将相关的回叫信道字符,确定下来,便于代码中识别调用。 const DEMOChannel='DemoChannel'; 2、服务器端对客户端的回叫 服务器端使用 TDServer组件的BroadcastMessage方法回叫所有注册的客户端。 TDServer组件重载了二个的BroadcastMessage方法 (1)使用二参数 function BroadcastMessage(const ChannelName:String; const Msg: TJSONValue; const ArgType:Integer=TDBXCallback.ArgJason):boolean; overload; 第1参数ChannelName指定通道中所有的回叫客户端; 第2参数Meg回传; 功能:通过Meg传递信息给带ChannelNamer指定的全部客户端。 (2)使用三参数 function BroadcastMessage(const ChannelName:String; const CallbackID:String; const Msg: TJSONValue; const ArgType:Integer=TDBXCallback.ArgJason):boolean; overload; 第1参数ChannelName指定通道中所有的回叫客户端; 第2参数CallbackID指定客户端的识别码; 第3参数Meg回传; 功能:通过Meg传递信息给带ChannelNamer中,指定的CallbackID客户端。 实例:例如在服务器端的TMemo1.onChange事件中: procedure TSMainFrm.mmMessageChange(Sender: TObject); var vMessage:TJSONString; begin vMessage := TJSONString.Create(mmMessage.Lines.Text); ServerContainer1.DSServer1.BroadcastMessage(DEMOChannel, vMessage); end; 3、服务器端对客户端注册的回叫通道的搜索 (1)搜索注册回叫通道的客户端ID,通过DSServer1.GetAllChannelClientId方法实现,代码如下: procedure TForm1.btnListAllClientIdsClick(Sender: TObject); var aIdList : TList<String>; sId : String; begin aIdList := ServerContainer5.DSServer1.GetAllChannelClientId(DEMOChannel); try for sId in aIdList do lbAllClientIds.Items.Add(sId); finally aIdList.Free; end; end; (2)搜索注册回叫通道客户端的回叫ID ,通过DSServer1.GetAllChannelCallbackId方法实现,代码如下: procedure TForm1.btnListAllCallbackIdsClick(Sender: TObject); var aIdList : TList<String>; sId : String; begin aIdList := ServerContainer5.DSServer1.GetAllChannelCallbackId(DEMOChannel); try for sId in aIdList do lbAllCallbackIds.Items.Add(sId); finally aIdList.Free; end; end; 二、客户端对回叫信道的设置 1、客户端注册 客户端注册回叫信道,由TDSClientCallbackChannelManager1.RegisterCallback方法实现;执行语句如下: TDSClientCallbackChanneManager1.RegisterCallback(Combobox1.Text, TDemoCallback.Create); 现在我们看一看,客户端向服务器端注册回叫信道时,上述代码包含了注册回叫通道的四个要素: (1)回叫通道ID,TDSClientCallbackChanneManager.ChannelNament属性值;相关字符应与服务器注册的“回叫信道”字符一致。 (2)客户端ID,TDSClientCallbackChanneManager.ManagerID属性值;每个客户端应明确一个唯一的识别码。 (3)回叫ID ,由TDSClientCallbackChanneManager1.RegisterCallback方法的第1个参数; (4)回叫方法,由TDSClientCallbackChanneManager1.RegisterCallback第2个参数带入,创建TDemoCallback继承的方法,该对象复载Execute方法,就是用于回叫识别。 2、客户端与客户端之间的回叫,使用TDSAdminClient类别的NotifyCallback方法 XE在DSProxy单元,增加TDSAdminClient类别,强化回叫功能。其中TDSAdminClient类别的NotifyCallback方法用于客户端之间的回叫,可以回叫指定回叫通道中的特定客户端(客户端ID)或回叫识别(回叫ID)的客户端。声明如下: function NotifyCallback(ChannelName:string; ClientID:string;CallbackID:string;Msg:TJSONValue; out Respones :TJSONValue):Boolean; NotifyCallback方法的参数含意: (1)ChannelName,回叫通道名称; (2)ClientID,客户端识别; (3)CallbackID,回叫识别; (4)Msg,传递信息; (5)Respones,被叫客户端的回传信息。 实例如下: procedure TfmMainForm.btnBroadcastToClientClick(Sender: TObject); var LClient: TDSAdminClient; LMessage: TJSONString; LResponse: TJSONValue; LConnection: TDBXConnection; begin LConnection := scnnCallbackServer.DBXConnection; LClient := TDSAdminClient.Create(LConnection, False); try LMessage := TJSONString.Create(Format('呼叫通道:%s,客户端识别:%s,回叫识别:%s,回叫信息:%s', [DemoChannelManager.ChannelName, cbClientIds.Text, cbCallbackIds.Text, mmChannelCallbacks.Text])); try LClient.NotifyCallback(DemoChannelManager.ChannelName, cbClientIds.Text, cbCallbackIds.Text, LMessage, LResponse); try if LResponse <> nil then edtResponse.Text := Format('客户端响应:%s', [LResponse.ToString]) else edtResponse.Text := Format('客户端响应:%s', ['nil']); finally LResponse.Free; end; finally LMessage.Free; end; finally LClient.Free; end; end;

5,498

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧