RTC Forums

Subscription => Support => Topic started by: Sorin on March 10, 2017, 01:43:36 PM



Title: Broadcast
Post by: Sorin on March 10, 2017, 01:43:36 PM
Hi,

Where I can find an example/hint about a server that can broadcast some messages to clients, or a client that can broadcast some messages to other clients ?


Title: Re: Broadcast
Post by: D.Tkalcec (RTC) on March 10, 2017, 01:48:24 PM
If you mean "UDP broadcasts", which are possible on Windows (no other platform supported) by using TRtcUdpClient and TRtcUdpServer components, then check example Projects in the "Demos/Raw_UDP" folder and make sure to use an UDP boardcast or multicast IP addres:
https://en.wikipedia.org/wiki/Broadcast_address
https://en.wikipedia.org/wiki/Multicast_address

But ... please note that RTC SDK is a HTTP-based component set with main focus on request/response-based protocols and there is not much documentation (only 1 simple example for each) and no official support for using raw UDP or TCP/IP components.

Best Regards,
Danijel Tkalcec


Title: Re: Broadcast
Post by: Sorin on March 10, 2017, 02:09:45 PM
My customers have a client application that from time to time "demands" from a web server RTC some information, as needed.
Now I want, if possible, to use the RTC Web Server to deliver on real-time to these client applications (and also to customers) that some critical information was changed.


Title: Re: Broadcast
Post by: D.Tkalcec (RTC) on March 10, 2017, 07:38:51 PM
Are your customers using your RTC Client Application to communicate with your RTC Server Application, or are they using some other (3rd-party) Client or a Web Browser to request information from your Server?

The most common way for Clients to get data from a Server using request/response-based protocols like HTTP, is for Clients to periodically send requests to the Server and ask if there is data for them available (polling).

An alternative to this approach, which does not require many changes to a Client already implemented to work with polling, is to use long polling, where a Client will ask the Server if there is data available (as in normal polling), but the Server (instead of responding immediately with "no data" if there is no data waiting for the Client) will keep Clients connection open and wait (without sending a response) until new data is available for that Client, or ... until a timeout (whichever happens first). Then, the Server will proces the request as usual, sending a response with or without data back to the Client. RTC Messenger Client/Server Demos and RTC Portal VCL Demos use this approach by utilizing "delayed calls" with RTC Remote Functions.

Third option would be to use RTC Gateway and Gate Client components which use a similar approach to long polling (described above), but instead of utilizing "delayed calls" with RTC remote functions, use a custom "binary packet" streaming protocol which is light-weight and faster than remote functions, but can ONLY be used with RTC Clients and RTC Servers (no 3rd-party support).

Best Regards,
Danijel Tkalcec


Title: Re: Broadcast
Post by: Sorin on March 13, 2017, 09:04:16 AM
My customers use an app created by me with RTC Components that call few remote functions from a RTC web server also created by me. the RTC Messenger or RTC Gateway are too complex to isolate (without support) this approach. Exists an example "light" ?


Title: Re: Broadcast
Post by: D.Tkalcec (RTC) on March 13, 2017, 11:06:07 AM
Sorry, but the only examples available are the ones I've already mentioned above.

Anyway ... because you have said that you are already using some mechanism to periodically request data from your Server and have mentioned "easy integration", I think that using "delayed calls" with RTC remote functions will be faster for you to implement than using a completely new set of components.

Even though this is the "old approach" which does require more manual coding and is probably more complicated than using RTC Gateway and Gate Client components, I don't really think there is so much to learn if you already know how to get data from a Server to a Client.

I will try to explain now how "delayed calls" work with RTC Remote Fuctions (in a "few" sentences), then include the "MsgGetDataExecute" method implementation, which is used by the RTC Messenger Server to implement the "get" remote function, which in turn is used by the RTC Messenger Client to get any data currently stored for that Client on the Server.

First, you will need a separate TRtcHttpClient component on your Client and you will need to use that component exclusively for sending requests to get data from the Server. The frequency of these requests does not really matter, because the Server will dictate how often a response is sent back if there is no data available.

The "gist" of "delayed calls" is the "OnExecute" event on the Server, where the remote function used by the Client to get new data has to be implemented.

It is not much different from what you are already doing now when periodically sending requests for data, but since you want the Clients to be notified almost immediately when new data is available from the Server, you will need to keep a remote function call in a "delayed response" state, so you can use a "WakeUp" method on a "TRtcDelayedCall" object (will be explained below), which you will create using the "PrepareDelayedCall" procedure from inside your "OnExecute" event on the Server (just keep reading ;)).

When writing your Server-side code to handle "delayed calls", you can either choose to have two different method implementations, one for direct calls made by Clients and a separate method for calls made internally when data is available, or ... as I've done it in the RTC Messenger Server example, simply store the current state of the remote function in one of the (unused) remote function parameters, like - for example - Param.asBoolean['delayed'] - which I am setting to TRUE when the remote function is called directly, so it will be TRUE later - when the same event is called as a result of "delayed calls" triggering.

You will also need to declare a local variable of type "TRtcDelayedCall" in your "OnExecute" event, so you can create an instance of it using the "PrepareDelayedCall" procedure (function declared in the "rtcSrvModule" unit) AFTER you have made sure the this Client is allowed to access data on your Server, but BEFORE you start checking if any data is available for that Client.

Since I am using the Param.asBoolean['delayed'] parameter to memorize the state of my remote function call, I will be creating a new "TRtcDelayedCall" object only if Param.asBoolean['delayed']=FALSE, but you can also have two separate event implementations if you want.

In either case, you will use the "PrepareDelayedCall" function if you want to have the abbility to delay a response if no data is available and call the same function internally again when data becomes available later.

Here are the "PrepareDelayedCall" function parameteres:
1. maximum allowed delay (in milliseconds) before a result has to be sent,
2. remote function call object (Param:TRtcFunctionInfo) and the
3. remote function call event (usually - the even you currently implementing).

When you get a new "TRtcDelayedCall" object, make sure to store it somewhere in your own structures and associate it with the user (Client) making this remote function call, so you can use the "WakeUp" method on the "TRtcDelayedCall" object when new data becomes available for that user (Client).

This "TRtcDelayedCall" object will be used to ensure that the "remote function call event" (whatever you've used as the 3rd parameter to the "PrepareDelayedCall" function) is triggered with remote function call parameters (whatever you have used as 2nd parameter) after the timeout (used as 1st parameter), or whenever you call the "WakeUp" method on the "TRtcDelayedCall" object - which you've received and should have stored somewhere in your structures associated with that user (client).

Once you have that "TRtcDelayedCall" object safely stored away inside your own structures, where it is accessible from any other parts of your code responsible for storing data for Clients, you can now check (from the same "OnExecute" event) if there is data available for that user (Client).

If there is data ready to be send immediately back to the user (Client) from the "OnExecute" event, if you have created a new "TRtcDelayedCall" object in this event, you should now REMOVE it from your own structures (make sure you will NOT be using that object anymore if new data arrives) and call the "CancelDelayedCall" procedure to free the "TRtcDelayedCall" object (avoid memory leaks), becuase that object is no longer required nor useful once we return any result back to the Client.

You can then prepare the Result for that Cient (as usual) and exist the remote function normally.

On the other hand ... if there was NO DATA ready to be sent back to the Client and you have created a new "TRtcDelayedCall" object (see above) and stored it safely in your own structures (so you can use its "WakeUp" method when new data does become available for the Client), you should use the "PostDelayedCall" procedure before you exist the "OnExecute" event to post your newly created "delayed call" and put your Clients conneciton with its remote function call into a "delayed response" state. This allows you to use the "WakeUp" method on the (previously created) "TRtcDelayedCall" object (which you should have stored somewhere in your structures and assiciated with that user/Client) to wake trigger this remote funciton call (where a new check for data will be made and a Result prepared for the Client) when new data does become available.

Or ... if there was NO DATA ready to be sent back to the Client, but you have NOT created a NEW "TRtcDelayedCall" object now, you should only REMOTE any previously created and stored "TRtcDelayedCall" objects from your own structures - before exiting the "OnExecute" event handler.

Here is the entire "MsgGetDataExecute" method implementation, which you can also find in the "rtcMessengerProvider.pas" unit. As you will see, even though my explanation was quite long, there is not a lot of code involved ...

Code:
procedure TMessenger_Provider.MsgGetDataExecute(Sender: TRtcConnection; Param: TRtcFunctionInfo; Result: TRtcValue);
  var
    thischeck:TDateTime;
    arr:TRtcArray;
    cb:TRtcDelayedCall;
  begin
  cb:=nil;

  CheckLogin(Sender, Param['user']);

  if not Param.asBoolean['delayed'] then
    begin
    { Set "delayed" parameter to TRUE, before preparing the call,
      because only changes we do to Param before we send it to
      the PrepareDelayedCall function will be memorized, while
      any changes we do to Param afterwards will be discarded. }
    Param.asBoolean['delayed']:=true;
    { Prepare delayed call, which will be triggered in 10 seconds
      in case the callback function is not used until then. }
    cb:=PrepareDelayedCall(10000, Param, MsgGetDataExecute);
    user.SetCallback(Param['user'],cb);
    end;

  arr:=user.GetData(Param['user'],Param['check'],thischeck);
  if assigned(arr) then
    begin
    // don't need delayed call, new data is ready to be sent now!
    user.SetCallback(Param['user'],nil);
    if assigned(cb) then
      CancelDelayedCall(cb);

    with Result.NewRecord do
      begin
      asObject['data']:=arr;
      asDateTime['check']:=thischeck;
      end;
    end
  else if assigned(cb) then
    PostDelayedCall(cb)
  else
    user.SetCallback(Param['user'],nil);
  end;

The "user" object in that example above is an instance of a custom class, which is implemented in the "rtcMessenger" unit in the Demos/DataProviders folder ad part of the RTC Messenger Server Demo and used for user management and data storage. You can check that unit for the actual implementation, if you need more details how it works.

If you have more question, feel free to ask.

Best Regards,
Danijel Tkalcec


Title: Re: Broadcast
Post by: Sorin on March 13, 2017, 11:30:50 AM
Thank you !
I will check this example.