第一范文网 - 专业文章范例文档资料分享平台

datasnap的初步

来源:用户分享 时间:2025/6/6 12:12:21 本文由loading 分享 下载这篇文档手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:xxxxxxx或QQ:xxxxxx 处理(尽可能给您提供完整文档),感谢您的支持与谅解。

datasnap的初步-回调函数

服务器端 TServerMethods1 =class(TComponent) private { Private declarations } public { Public declarations } functionTest(funcCallBack: TDBXCallback):boolean; end; functionTServerMethods1.Test(funcCallBack: TDBXCallback):boolean; begin funcCallBack.Execute(TJSONNumber.Create(20)).Free; sleep(1000); Result :=True; end; 客户端,这个必须继承自TDBXCallback TFuncCallback =class(TDBXCallback) functionExecute(constArg: TJSONValue): TJSONValue;override; end; functionTFuncCallback .Execute(constArg: TJSONValue): TJSONValue; var i:Integer; begin i := TJSONNumber(Arg).AsInt;//可以的到服务器回调来的参数 Result := TJSONNull.Create; end; procedureTForm2.Button1Click(Sender: TObject); begin ClientModule1.ServerMethods1Client.Test(funcCallBack); end; initialization funcCallBack:= TFuncCallBack.Create; finalization //FreeAndNil(funcCallBack);

到此,实现了最基本的回叫。

D2010起提供了DSClientCallbackChannelManager这个控件,这是为了实现一次注册,多次回叫,使用方法很简单

1。客户端使用 DSClientCallbackChannelManager注册回叫函数 function RegisterCallback(const CallbackId: String; const Callback: TDBXCallback): boolean; overload; DSClientCallbackChannelManager控件带有一个ChannelName的属性,用于CallbackId分组用。ManagerId属性,可理解为ClientId,ClientId必须是唯一的,相同的ClientId,会被认为是相同地点来的连接。

不明白为啥 DSClientCallbackChannelManager要自己设置连接属性,而不是走TSQLConnection。

2。服务器端是TDSServer来做事,它有 两个函数 function BroadcastMessage(const ChannelName: String; const Msg: TJSONValue; const ArgType: Integer = TDBXCallback.ArgJson): boolean; overload; function BroadcastMessage(const ChannelName: String; const CallbackId: String; const Msg: TJSONValue; const ArgType: Integer = TDBXCallback.ArgJson): boolean; overload; 第一个函数,回调在ChannelName里面所有的callbackid, 第二个是回调ChannelName里面指定的CallBackId

服务器上用GetAllChannelCallbackId能返回在某个ChannelName里面所有的CallbackId。

到此,我们就能使用DSClientCallbackChannelManager来制作一个简单的聊天软件,并能实现私聊的功能。但是如何处理,聊天用户掉线的问题,就比较麻烦了。

和RO比较,这设计有些像RO里的TROEventReceiver,但远没RO灵活, TROEventReceiver直接就能订阅(RegisterEventHandlers)上一堆服务器的事件,DataSnap却要定义一堆的TDBXCallback。

datasnap的初步 TDSClientCallbackChannelManager的工作方式

理解一下TDSClientCallbackChannelManager的工作方式吧

客户端调用RegisterCallback,其实就是开始了一个线程TDSChannelThread,该线程起一个dbxconnection,连接到服务器上,执行DSAdmin.ConnectClientChannel,服务器上的这个DSAdmin.ConnectClientChannel很神奇,所有的数据传输都在这里了,这个连接不会关闭,以做到服务器往客户端push数据。TDSClientCallbackChannelManager只能做到服务器向客户端推送数据,单向的。客户端要向服务器送数据,走TDSAdminClient的NotifyCallback方法,也就是只有经过SQLConnection。

DSAdmin(在Datasnap.DSCommonServer单元)是TDBXServerComponent(在Datasnap.DSPlatform单元)的子类,ConnectClientChannel函数直接call ConsumeAllClientChannel。 代码摘抄 functionTDBXServerComponent.ConsumeAllClientChannel(constChannelName, ChannelId, CallbackId, SecurityToken:String; ChannelNames: TStringList; ChannelCallback: TDBXCallback; Timeout:Cardinal):Boolean; ... begin // wait for exit message repeat //这里开始 Data :=nil; IsBroadcast :=false; ArgType := TDBXCallback.ArgJson; QueueMessage :=nil; TMonitor.Enter(CallbackTunnel.Queue); try {Wait for a queue item to be added if the queue is empty, otherwise don't wait and just pop the next queue item} ifCallbackTunnel.Queue.QueueSize =0then IsAquired := TMonitor.Wait(CallbackTunnel.Queue, Timeout) else IsAquired :=true; ifIsAquiredand(CallbackTunnel.Queue.QueueSize >0)then begin {Get the next queued item from the tunnel} QueueMessage := CallbackTunnel.Queue.PopItem; Data := QueueMessage.Msg; IsBroadcast := QueueMessage.IsBroadcast; ArgType := QueueMessage.ArgType; end; finally TMonitor.Exit(CallbackTunnel.Queue); end; ifIsAquiredand(Data <>nil)then ifIsBroadcastthen begin try Msg := TJSONObject.Create(TJSONPair.Create('broadcast', TJSONArray.Create(Data).Add(ArgType))); if(QueueMessage.ChannelName <> EmptyStr)and (QueueMessage.ChannelName <> CallbackTunnel.ServerChannelName)then Msg.AddPair(TJSONPair.Create('channel', QueueMessage.ChannelName)); try ChannelCallback.Execute(Msg).Free; except try // Remove the callback tunnel from the list, it will be freed at the end of this method InternalRemoveCallbackTunnel(DSServer, CallbackTunnel); except end; raise; end; finally QueueMessage.InstanceOwner :=false; FreeAndNil(QueueMessage); end; end elseifAssigned(QueueMessage)then begin TMonitor.Enter(QueueMessage); try Msg := TJSONObject.Create( TJSONPair.Create('invoke', TJSONArray.Create( TJSONString.Create(QueueMessage.CallbackId), Data).Add(ArgType))); try QueueMessage.Response := ChannelCallback.Execute(Msg); except onE : Exceptiondo begin QueueMessage.IsError :=True; QueueMessage.Response := TJSONObject.Create(TJSONPair.Create('error', E.Message)); ifChannelCallback.ConnectionLostthen begin WasConnectionLost :=True; TMonitor.Pulse(QueueMessage); try // Remove the callback tunnel from the list, it will be freed at the end of this method InternalRemoveCallbackTunnel(DSServer, CallbackTunnel); except end;

搜索更多关于: datasnap的初步 的文档
datasnap的初步.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.diyifanwen.net/c038631lld29kfa251dwf_1.html(转载请注明文章来源)
热门推荐
Copyright © 2012-2023 第一范文网 版权所有 免责声明 | 联系我们
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:xxxxxx 邮箱:xxxxxx@qq.com
渝ICP备2023013149号
Top