標(biāo)題: |
斗膽開個(gè)Datasnap交流貼 |
瀏覽:2561 |
|
加入我的收藏 |
樓主: |
首先聲明,開此貼僅并不是想說明Datasnap的好與不好,也不包含其它任何比較之意,僅是靠個(gè)人對(duì)Delphi的喜愛而開此貼。
限于各種原因,本人并沒有什么Datasnap的實(shí)際經(jīng)驗(yàn),只是業(yè)余時(shí)間喜歡“把玩”--寫些小DEMO測(cè)試,所以很抱歉,無法提供Datasnap的一些性能測(cè)試的數(shù)據(jù),僅能提供少許寫DEMO時(shí)的體會(huì),即希望能拋磚引玉,也希望對(duì)剛接觸Datasnap的新人有所幫助。若有不正確之處,歡迎指出。
如果“臟”了誰的眼,勿噴,請(qǐng)繞行。
----------------------------------------------
學(xué)無止境 |
作者: |
jjwwang (jjwwang) |
▲▲▲▲▲ |
-
|
注冊(cè)會(huì)員 |
|
2015-1-13 12:21:52 |
1樓: |
鄙人將整理一些之前的DEMO,找時(shí)間上來補(bǔ)充----雖然有些可能在網(wǎng)上能搜到。
----------------------------------------------
學(xué)無止境
|
作者: |
|
2015-1-13 12:30:28 |
2樓: |
呵呵頂一個(gè),
----------------------------------------------
-
|
作者: |
jjwwang (jjwwang) |
▲▲▲▲▲ |
-
|
注冊(cè)會(huì)員 |
|
2015-1-13 13:23:12 |
4樓: |
在寫代碼之前,首先要考慮使用的協(xié)議類型, 是tcp/ip還是http(s),不同的協(xié)議對(duì)應(yīng)不同的設(shè)計(jì),tcp/ip是長(zhǎng)連,服務(wù)器端可以知道當(dāng)前有多少在線用戶,http可以方便的改為IIS方式,不同的協(xié)議類型,Server Class LifeCycle(Server Class是指TDSServerClass)可以有不同的選擇,不同的選擇對(duì)應(yīng)不同的設(shè)計(jì), Server Class LifeCycle對(duì)于Datasnap的性能是非常重要的,分為 Server, Session, Invocation三種,每種類型的特點(diǎn),網(wǎng)上可搜到相關(guān)文章或李維先生的電子書。
對(duì)于服務(wù)程序的性能,除硬件外就是靠軟件方面的優(yōu)化了,Datasnap內(nèi)部使用的是indy組件,是阻塞的,每次響應(yīng)都依賴一個(gè)線程,datasnap本身提供了“池”的功能。所以服務(wù)方法要盡快的完成,好讓線程回到池中再利用。在并發(fā)和負(fù)載較大的程序中是很重要的。所以不管是tcp或http,盡量分批取少量的數(shù)據(jù),如果的確要取大量的數(shù)據(jù),不如直接開個(gè)dbxcallback(回調(diào))更好,還可以在客戶端顯示進(jìn)度。
----------------------------------------------
學(xué)無止境
|
作者: |
judger (ERP) |
▲▲▲▲▲ |
-
|
盒子活躍會(huì)員 |
|
2015-1-13 13:29:43 |
5樓: |
為了回復(fù)你,我登錄了一下系統(tǒng),支持?。?!
----------------------------------------------
-
|
作者: |
jjwwang (jjwwang) |
▲▲▲▲▲ |
-
|
注冊(cè)會(huì)員 |
|
2015-1-13 13:39:15 |
5樓: |
除了分批次,少量取數(shù)據(jù)提高性能外,服務(wù)方法中參數(shù)的數(shù)據(jù)類型也會(huì)對(duì)性能有影響,Datasnap是基于DBX framework的,在delphi幫助提到 Currently, using a TDBXValue is the fastest way to pass a parameter, because these are the internal objects used to manage parameter lists. 如果參數(shù)是一般的string等簡(jiǎn)單類型,基本可以忽略,但如果參數(shù)是TStream類型時(shí),可以用TDBXStreamValue來替換,記得在XE2時(shí)候測(cè)試過,比一般TStream類型節(jié)約30%的返回時(shí)間。
----------------------------------------------
學(xué)無止境
|
作者: |
|
2015-1-13 13:40:50 |
4樓: |
好帖,頂樓主!
----------------------------------------------
==========
|
作者: |
jjwwang (jjwwang) |
▲▲▲▲▲ |
-
|
注冊(cè)會(huì)員 |
|
2015-1-13 13:56:59 |
6樓: |
感謝judger (ERP)的支持.
繼續(xù) function CreateDBXStreamValue: TDBXStreamValue; var VT: TDBXValueType; begin VT := TDBXValueType.Create(nil); VT.DataType := TDBXDataTypes.BlobType; VT.ValueTypeFlags := TDBXValueTypeFlags.ExtendedType; Result := TDBXStreamValue.Create(VT); end; 創(chuàng)建一個(gè)TDBXStreamValue可用上面的代碼, VT.ValueTypeFlags := TDBXValueTypeFlags.ExtendedType;這行代碼在XE2中,好像是需要的,在XE?好像不再需要了(或許也需要)記不清了(當(dāng)時(shí)是寫DEMO跟蹤發(fā)現(xiàn)的,心血?。?。 procedure SetStream(const Stream: TStream; const AInstanceOwner: Boolean); override; function GetStream(AInstanceOwner: Boolean): TStream; override; 這兩個(gè)方法對(duì)應(yīng)服務(wù)端和客戶端的取值,其中的AInstanceOwner參數(shù)比較重要,可能會(huì)造成內(nèi)存泄漏或報(bào)異常,客戶端需要和下面TServerMethodsClient的Create方法搭配使用。 TServerMethodsClient.Create(ADBXConnection: TDBXConnection; AInstanceOwner: Boolean); overload; 實(shí)際上,TServerMethodsClient.Create中的AInstanceOwner是比較重要的,在傳一些對(duì)象參數(shù)時(shí),需要注意。后面我會(huì)寫一些經(jīng)驗(yàn),但還是要靠個(gè)人摸索掌握。
----------------------------------------------
學(xué)無止境
|
作者: |
looper (keyo) |
★☆☆☆☆ |
-
|
盒子活躍會(huì)員 |
|
2015-1-13 14:06:36 |
7樓: |
難得有這種好帖子。支持一下。
----------------------------------------------
雖千萬人吾往矣!
|
作者: |
jjwwang (jjwwang) |
▲▲▲▲▲ |
-
|
注冊(cè)會(huì)員 |
|
2015-1-13 14:20:32 |
7樓: |
除了參數(shù)類型外,通過Server Class LifeCycle的Server, Session, Invocation三種類型,還可以"榨出"Datasnap一些性能來,這個(gè)技巧應(yīng)該在XE or XE2時(shí)就有了,當(dāng)時(shí)EMB在土豆,奇藝上發(fā)過一些視頻,基中就有介紹,目前在EMB的網(wǎng)站上也還有。具體的代碼就不上了,主要是說說原理。 當(dāng)使用tcp協(xié)議時(shí),TDSServerClass的LifeCycle可以設(shè)置為Server,Session, Invocation的一種,http時(shí),delphi的文檔上說: For a REST client connection, if Session LifeCycle is used on the server class, it behaves like Invocation LifeCycle. 所以利用Invocation類型,我們可以緩存TDSServerClass實(shí)例。具體辦法是 在TDSServerClass的OnCreateInstance和OnDestroyInstance事件中池化TDSServerClass的實(shí)例,這和網(wǎng)上寫的監(jiān)控客戶端連接是一個(gè)意思。
----------------------------------------------
學(xué)無止境
|
作者: |
jjwwang (jjwwang) |
▲▲▲▲▲ |
-
|
注冊(cè)會(huì)員 |
|
2015-1-13 14:46:47 |
8樓: |
除此之外,涉及到數(shù)據(jù)庫的,自覺使用連接池(自己實(shí)現(xiàn)也好,用fdac的也好) 一般的數(shù)據(jù)查詢,使用DBX framework時(shí),返回DBXReader最好了。(目前未與直接返回TDataset對(duì)比過,感覺dataset最終也會(huì)轉(zhuǎn)為dbxreader)
慎用TDSClientCallbackChannelManager的注冊(cè)回調(diào),除非只是為了接收其它客戶端或服務(wù)器端的消息。 如果有SQLConnection產(chǎn)生一個(gè)連接了, 不要用TDSClientCallbackChannelManager的BroadcastToChannel或NotifyCallback方法,而要通過SQLConnection調(diào)用服務(wù)器的一個(gè)方法進(jìn)行廣播或通知其它客戶端----原因后續(xù)再說明。
----------------------------------------------
學(xué)無止境
|
作者: |
|
2015-1-13 18:14:46 |
9樓: |
好貼,嚴(yán)重支持
----------------------------------------------
-
|
作者: |
yemny (yemny) |
▲▲▲▲▲ |
-
|
盒子活躍會(huì)員 |
|
2015-1-13 18:59:59 |
10樓: |
鼓掌 頂 支持 威武 比口水 睡好 睡不好 個(gè)人感覺 好 5倍
----------------------------------------------
-
|
作者: |
yagzh (心不了情) |
▲▲▲▲▲ |
-
|
盒子活躍會(huì)員 |
|
2015-1-13 19:26:58 |
11樓: |
頂一下
----------------------------------------------
-
|
作者: |
|
2015-1-14 8:00:03 |
12樓: |
對(duì)初學(xué)者有意義的,支持
----------------------------------------------
-
|
作者: |
|
2015-1-14 9:41:17 |
13樓: |
將帖子標(biāo)注為好帖,將LZ標(biāo)注為高手
----------------------------------------------
-
|
作者: |
fky1989 (fky1989) |
▲▲▲△△ |
-
|
注冊(cè)會(huì)員 |
|
2015-1-14 9:44:10 |
14樓: |
好貼 支持lZ
----------------------------------------------
-
|
作者: |
looper (keyo) |
★☆☆☆☆ |
-
|
盒子活躍會(huì)員 |
|
2015-1-15 14:08:36 |
15樓: |
頂。
----------------------------------------------
雖千萬人吾往矣!
|
作者: |
pengmg (Challey) |
▲▲▲▲▲ |
-
|
普通會(huì)員 |
|
2015-1-15 19:23:37 |
16樓: |
是的,請(qǐng)有過實(shí)際案例的把情況發(fā)上來,討論討論
----------------------------------------------
-
|
作者: |
|
2015-1-18 10:37:52 |
17樓: |
好貼! 另外請(qǐng)教一個(gè)問題:
datasnap服務(wù)器上的方法,如果用http方式請(qǐng)求的話,他會(huì)返回 {"result":[{"name":"123","dfd":1}]} 這種格式,能有辦法讓他直接返回 {"name":"123","dfd":1} 這樣的格式嗎?
----------------------------------------------
-
|
作者: |
|
2015-1-18 11:09:15 |
18樓: |
好?。?!
----------------------------------------------
-
|
作者: |
jjwwang (jjwwang) |
▲▲▲▲▲ |
-
|
注冊(cè)會(huì)員 |
|
2015-1-18 14:19:16 |
19樓: |
to: hzforce ( )
//----------
procedure TWebModule1.DSHTTPWebDispatcher1FormatResult(Sender: TObject; var ResultVal: TJSONValue; const Command: TDBXCommand; var Handled: Boolean); begin Form1.Memo1.Lines.Add(command.Text); Form1.Memo1.Lines.Add(ResultVal.ToString); if Command.Text='TServerMethods1.ReverseString' then Handled := True else Handled := False; end;
//---------- IE: http://localhost:8080/datasnap/rest/TServerMethods1/ReverseString/abc
//---------- 測(cè)試結(jié)果:
["cba"]
----------------------------------------------
學(xué)無止境
|
作者: |
|
2015-1-18 15:36:55 |
20樓: |
每天來看看樓主有沒有更新,謝謝!
----------------------------------------------
-
|
作者: |
jjwwang (jjwwang) |
▲▲▲▲▲ |
-
|
注冊(cè)會(huì)員 |
|
2015-1-18 19:59:58 |
21樓: |
謝謝dawnhawk (dawnhawk)和其它朋友的關(guān)注,這幾天有點(diǎn)事情耽擱了。 總體來說,datasnap用起來是比較簡(jiǎn)單的,從精靈向?qū)梢约跋嚓P(guān)的組件屬性,事件,方法上也可以看出來,所以使用中可控的東西不是很多----從XE5之后,datasnap基本上沒有什么變化。
下面繼續(xù)寫下之前說的TDSClientCallbackChannelManager注冊(cè)回調(diào)。
用TDSClientCallbackChannelManager注冊(cè)一個(gè)回調(diào)后,會(huì)產(chǎn)生一個(gè)新的連接,如果再調(diào)用TDSClientCallbackChannelManager.NotifyXXXX 或 BroadcastXXXX的時(shí)候,還會(huì)新建一個(gè)連接,然后再斷開,并且TDSClientCallbackChannelManager在取消注冊(cè)的回調(diào)時(shí),會(huì)產(chǎn)生連接,斷開,連接,斷開至少兩次。所以頻繁的用TDSClientCallbackChannelManager發(fā)送消息,會(huì)頻繁的產(chǎn)生連接,斷開,對(duì)服務(wù)程序會(huì)有一定的影響。
所以使用TDSClientCallbackChannelManager的時(shí)機(jī),應(yīng)該是“只為了被動(dòng)的接收其它客戶端或服務(wù)端的消息通知”,這種方式實(shí)際上屬于“服務(wù)端推送”的方式。當(dāng)程中已經(jīng)有一個(gè)用SQLConnection建立的連接時(shí),更不要用TDSClientCallbackChannelManager去發(fā)送信息,最好服務(wù)器程序中提供類似這樣的方式: function NotifyCallback(const AChannelName, AClientId, AValue: string): Boolean; begin Result := FDSServer.BroadcastMessage(AChannelName, AClientId, TJSonString.Create(AValue)); end 用SQLConnection的現(xiàn)有連接去執(zhí)行消息的廣播,這樣就減少了服務(wù)程序的連接,斷開次數(shù)。
----------------------------------------------
學(xué)無止境
|
作者: |
|
2015-1-22 14:56:47 |
22樓: |
感謝樓主的指教. 現(xiàn)在又有一個(gè)新的問題
我現(xiàn)在想使用https協(xié)議,我的做法是增加了一個(gè)TDSCertFiles控件,然后設(shè)置好TDSHTTPService的CertFile屬性,然后下載了一個(gè)最新openssl,把需要的那兩個(gè)dll文件放在程序的目錄底下,然后我用https://localhost:8081/datasnap/rest/TServerMethods1/ReverseString/abc提交的時(shí)候就出現(xiàn)問題了,提示如下: First chance exception at $7544B760. Exception class EIdOSSLUnderlyingCryptoError with message 'Error accepting connection with SSL. error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher'. Process Project1.exe (4656)
First chance exception at $7544B760. Exception class EIdOSSLUnderlyingCryptoError with message 'Error accepting connection with SSL. error:1408A10B:SSL routines:SSL3_GET_CLIENT_HELLO:wrong version number'. Process Server_Controller.exe (1224)
我已經(jīng)換過好幾個(gè)openssl的版本了,還是不行,請(qǐng)問這個(gè)會(huì)是什么原因呢? 我的系統(tǒng)是 win7 32位 + XE7 update1
----------------------------------------------
-
|
作者: |
|
2015-1-22 16:01:14 |
23樓: |
唉,原來證書問題~~~
----------------------------------------------
-
|
作者: |
jjwwang (jjwwang) |
▲▲▲▲▲ |
-
|
注冊(cè)會(huì)員 |
|
2015-1-26 16:32:52 |
24樓: |
今天又發(fā)現(xiàn)個(gè)問題,TCP連接方式,TDSClientCallbackChannelManager注冊(cè)回調(diào)后,心跳功能不起作用,只有服務(wù)端執(zhí)行回調(diào)時(shí),才會(huì)觸發(fā)異常。
----------------------------------------------
學(xué)無止境
|
作者: |
jjwwang (jjwwang) |
▲▲▲▲▲ |
-
|
注冊(cè)會(huì)員 |
|
2015-1-29 0:16:30 |
25樓: |
TDSClientCallbackChannelManager注冊(cè)回調(diào)后,服務(wù)端的連接線程會(huì)被”掛起“ 相當(dāng)于WaitForSingleObject的INFINITE死等,如果網(wǎng)路異常斷開,會(huì)一直掛著,除非網(wǎng)絡(luò)連通后,客戶端重新注冊(cè)回調(diào)。
所以最好周期性用DSServer.notifyxxxx 去發(fā)送一個(gè)TJSONNull的消息,用來“激活”線程,線程激活后會(huì)產(chǎn)生正常的Disconnect事件。否則掛”死“的線程會(huì)起來越多,服務(wù)程序早晚會(huì)掛了。
----------------------------------------------
學(xué)無止境
|
作者: |
topok (topok) |
▲▲▲▲▲ |
-
|
盒子活躍會(huì)員 |
|
2015-1-29 9:22:54 |
26樓: |
delphi哪個(gè)版本的Datasnap穩(wěn)定高效,網(wǎng)上有人說XE3的非常不穩(wěn)定而且還特別慢
----------------------------------------------
-
|
作者: |
jjwwang (jjwwang) |
▲▲▲▲▲ |
-
|
注冊(cè)會(huì)員 |
|
2015-1-31 0:54:12 |
27樓: |
發(fā)現(xiàn)XE7的一個(gè)BUG。
unit Unit1;
interface
uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IPPeerClient, Datasnap.DSCommon, Vcl.StdCtrls, Data.DBXJSON, System.JSON;
type TForm1 = class(TForm) Button1: TButton; Button2: TButton; DSCCM: TDSClientCallbackChannelManager; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure FormCreate(Sender: TObject); private public { Public declarations } end;
TCB = class(TDBXCallback) public function Execute(const Arg: TJSONValue): TJSONValue; overload; override; end;
var Form1: TForm1;
Flag: Boolean;
implementation
{$R *.dfm}
{ TCB }
function TCB.Execute(const Arg: TJSONValue): TJSONValue; begin Result := TJSONTrue.Create; end;
procedure TForm1.Button1Click(Sender: TObject); begin Flag := DSCCM.RegisterCallback('A', TCB.Create); end;
procedure TForm1.Button2Click(Sender: TObject); begin if Flag then DSCCM.UnregisterCallback('A'); end;
procedure TForm1.FormCreate(Sender: TObject); begin ReportMemoryLeaksOnShutdown := True; end;
end.
注冊(cè)回調(diào)后,再反注冊(cè),再注冊(cè),再反注冊(cè)。就會(huì)有內(nèi)存泄漏了。
----------------------------------------------
學(xué)無止境
|
作者: |
|
2015-1-31 0:59:06 |
27樓: |
TO:jjwwang
繼續(xù)普及下周期性用DSServer.notifyxxxx 線程激活后會(huì)產(chǎn)生正常的Disconnect事件
----------------------------------------------
-
|
作者: |
jjwwang (jjwwang) |
▲▲▲▲▲ |
-
|
注冊(cè)會(huì)員 |
|
2015-1-31 1:01:24 |
28樓: |
function TDSClientCallbackChannelManager.RegisterCallback( const CallbackId, ChannelNames: string; const Callback: TDBXCallback): Boolean; var Status: Boolean; Item, LItem: TDSCallbackItem; begin TMonitor.Enter(FLocalCallbackRepo); try if not FLocalCallbackRepo.ContainsKey(CallbackId) then begin Item := TDSCallbackItem.Create(FChannelName, Callback, ChannelNames); FLocalCallbackRepo.Add(CallbackId, Item);
if FLocalCallbackRepo.Count = 1 then begin FState := ctsStarted; FStateError := EmptyStr;
// start a thread if this is the first registered callback (check if there an active one) {**********} FDSChannelThread := TDSChannelThread.Create( 每注冊(cè)一次回調(diào)就創(chuàng)建一個(gè)線程。 {**********} procedure begin try ExecuteRemote('DSAdmin', 'ConnectClientChannel', procedure (Params: TDBXParameterList) begin Params[0].Value.AsString := FChannelName; Params[1].Value.AsString := FManagerId;
但是:
constructor TDSClientCallbackChannelManager.TDSChannelThread.Create( Worker: TDSWorker; Manager: TDSClientCallbackChannelManager); begin FWorker := Worker; FManager := Manager; {**********} FreeOnTerminate := False; 這里不是自動(dòng)釋放線程資源 {**********} inherited Create(False); // Suspended end;
并且:
destructor TDSClientCallbackChannelManager.Destroy; begin try // unregister all outstanding callbacks CloseClientChannel(); except // igonore I/O errors at this point end; {**********} TDSClientCallbackChannelManager釋放的時(shí)候,F(xiàn)DSChannelThread 只釋放一次。 {**********888} if FDSChannelThread <> nil then begin FDSChannelThread.WaitFor; FDSChannelThread.Free; end; {**********8}
所以多次注冊(cè),多次創(chuàng)建了線程,但只有一個(gè)能釋放。
----------------------------------------------
學(xué)無止境
|
作者: |
jjwwang (jjwwang) |
▲▲▲▲▲ |
-
|
注冊(cè)會(huì)員 |
|
2015-1-31 1:04:08 |
29樓: |
建議:
動(dòng)態(tài)創(chuàng)建TDSClientCallbackChannelManager進(jìn)行回調(diào)注冊(cè),取消回調(diào)或注冊(cè)回調(diào)失敗后,立即釋放TDSClientCallbackChannelManager。 再注冊(cè)的時(shí),重復(fù)上面的過程。
----------------------------------------------
學(xué)無止境
|
作者: |
jjwwang (jjwwang) |
▲▲▲▲▲ |
-
|
注冊(cè)會(huì)員 |
|
2015-1-31 1:20:02 |
30樓: |
to: wiseinfo (wisienfo)
只是粗略的跟蹤了一下D的代碼,大體感覺是這樣子。 實(shí)際上,只要服務(wù)程序通知回調(diào)的時(shí)間周期不是很長(zhǎng)的話,應(yīng)該也沒有什么問題。
----------------------------------------------
學(xué)無止境
|
作者: |
jjwwang (jjwwang) |
▲▲▲▲▲ |
-
|
注冊(cè)會(huì)員 |
|
2015-1-31 22:14:03 |
31樓: |
閑暇之余又看了看TDSClientCallbackChannelManager的代碼,越想越覺得起火,感覺就是臨時(shí)對(duì)付著寫的,EMB的工程師根本沒用心。
主要問題:
1 RegisterCallback反回值并不能代碼注冊(cè)回調(diào)成功與否。由于在TDSChannelThread線程中向服務(wù)程序注冊(cè)TDBXCallback, 所以RegisterCallback方法的返回值是在線程執(zhí)行完之前返回的,并不能表時(shí)TDSChannelThread注冊(cè)回調(diào)成功了。
2 TDSChannelThread線程中產(chǎn)生異常時(shí),觸發(fā)TDSClientChannelManagerEvent事件,所以開發(fā)者在TDSClientChannelManagerEvent事件中寫的代碼,即可能是在主線程中,也可能是在TDSChannelThread線程。不注意時(shí),可能給開發(fā)者帶來麻煩。
3 注銷回調(diào)的UnregisterCallback方法,要與服務(wù)程序 【連接,斷開】 2次。 難道就不能用一個(gè)連接去讓服務(wù)程序做事嗎?
4 TDSChannelCallback, TDSChannelThread, TDSChannelInvokeEvent都是內(nèi)部的。 想借用點(diǎn)源代都不容易。
----------------------------------------------
學(xué)無止境
|
作者: |
jjwwang (jjwwang) |
▲▲▲▲▲ |
-
|
注冊(cè)會(huì)員 |
|
2015-1-31 22:30:53 |
32樓: |
替代方法:
1 用SQLConnection連接Datasnap服務(wù)。 2 創(chuàng)建DBXCommand,然后按照TDSClientCallbackChannelManager下面的代碼片段的方式,自己寫代碼注冊(cè)回調(diào), ExecuteRemote('DSAdmin', 'ConnectClientChannel', procedure (Params: TDBXParameterList) begin Params[0].Value.AsString := FChannelName; Params[1].Value.AsString := FManagerId; Params[2].Value.AsString := CallbackId; Params[3].Value.AsString := ChannelNames; Params[4].Value.AsString := FSecurityToken; Params[5].Value.SetCallbackValue(FChannelCallback); end, 補(bǔ)充說明: 如果Datasnap的服務(wù)程序上的ChannelName中已經(jīng)存在ClientID客戶端標(biāo)識(shí)的話,注冊(cè)是不會(huì)成功的,所以 [不是] 首次注冊(cè)回調(diào)時(shí),要先從服務(wù)端清除掉之前的ChannelName中的ClientID.具體方法,參照TDSClientCallbackChannelManager中注銷回調(diào)的源代碼。
這樣一來,可以避免多次和服務(wù)程序的 連接,斷后次數(shù),減輕服務(wù)程序的壓力。
----------------------------------------------
學(xué)無止境
|
作者: |
lulugo (找上帝說理) |
▲▲▲▲▲ |
-
|
盒子活躍會(huì)員 |
|
2015-2-1 16:51:29 |
33樓: |
關(guān)注
----------------------------------------------
-努力成就未來....
|
作者: |
wuxi15 (似水·流年) |
▲▲▲△△ |
-
|
注冊(cè)會(huì)員 |
|
2015-2-1 17:22:41 |
34樓: |
頂樓主。 各位想了解Datasnap客戶端互動(dòng)的可以看一下XE6的Demo。XE7下很多Demo沒有了。 XE6下的Demo比較齊全,客戶端與服務(wù)端通訊,客戶端與客戶端通訊都有
----------------------------------------------
我愛Delphi,我用Delphi http://www.cnblogs.com/wuxi15 |
|