USEGEAR

导航

datasnap的回调广播

感觉中的datasnap千孔百疮,到xe10已经具备冲击成千上万用户并发的能力了。应该放心用于项目实战了。补课研究10.1 datasnap开发手册。

用到的方法:

    (1)TDBXCallback机制;
    (2)TDServer.BroadcastMessage方法;
    (3)TDSClientCallbackChanneManager1.RegisterCallback方法;

    一、回叫的方式
    1、服务器端回叫所有(同一信道)客户端
    2、客户端回叫(同一信道)的其它客户端                                                                       
    3、客户端可以注册多个信道

server:

  1.   定义信道。定一条通道公路,然后搜索在此通道上跑的的car。得到每个客户ID
const DEMOChannel='DemoChannel';

        2.服务器对客户端回调:

procedure TSMainFrm.mmMessageChange(Sender: TObject);
var vMessage:TJSONString;
begin
  vMessage := TJSONString.Create(mmMessage.Lines.Text);
  ServerContainer1.DSServer1.BroadcastMessage(DEMOChannel, vMessage);
end;

       3.对客户端注册通道和回调通道的搜索,由此得到通道中客户端的ID

procedure TForm1.btnListAllClientIdsClick(Sender: TObject);
var
  aIdList : TList<String>;
  sId : String;
begin
  aIdList := ServerContainer5.DSServer1.GetAllChannelClientId(DEMOChannel);{得到该通道中all的客户端ID}
  try
    for sId in aIdList do
      lbAllClientIds.Items.Add(sId);
  finally
    aIdList.Free;
  end;
end;
procedure TForm1.btnListAllCallbackIdsClick(Sender: TObject);
var
  aIdList : TList<String>;
  sId : String;
begin
  aIdList := ServerContainer5.DSServer1.GetAllChannelCallbackId(DEMOChannel);{得到该回调通道中all的客户端ID
  try
    for sId in aIdList do
      lbAllCallbackIds.Items.Add(sId);
  finally
    aIdList.Free;
  end;
end;

Client:

       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方法,就是用于回叫识别。

//首先继承类TDBXCallback 
TDemoCallback = class(TDBXCallback) public constructor Create; function Execute(const Arg: TJSONValue): TJSONValue; override; end;
//TDemoCallback的excute方法。注意线程异步调用
function
TDemoCallback.Execute(const Arg: TJSONValue): TJSONValue; var sDemoMessage : String; begin Result := TJSONTrue.Create; if (Arg is TJSONString) then begin sDemoMessage := TJSONString(Arg).Value; TThread.Synchronize(nil, procedure begin fmMainForm.mmDemoMessage.Lines.Text := sDemoMessage; end ); end; end;
procedure TfmMainForm.btnStartClick(Sender: TObject);
begin
  SetupTask;
  EnableDisableButtons(False, True);
  DemoChannelManager.RegisterCallback(callbackId, DemoCallback.Create);//注册通道
end;

procedure TfmMainForm.btnStopClick(Sender: TObject);
begin
  EnableDisableButtons(True ,False);
  DemoChannelManager.UnregisterCallback(callbackId);//注销
end;
procedure TForm17.mmMessageChange(Sender: TObject);//服务器通过回调发送信息到该通道all客户端
var
  vMessage : TJSONString;
begin
  vMessage := TJSONString.Create(mmMessage.Lines.Text);
  ServerContainer5.DSServer1.BroadcastMessage(DEMOChannel, vMessage);//发送信息到该通道DEMOChannel中all的客户端
end;

 

    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;

 

posted on 2020-03-17 16:20  USEGEAR  阅读(690)  评论(0编辑  收藏  举报