RTC Forums
November 24, 2024, 09:58:45 PM *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
   Home   Help Login Register  
Pages: [1]
  Print  
Author Topic: Server Triggered message to Client  (Read 6049 times)
zsleo
RTC Expired
*
Posts: 80


« on: February 22, 2012, 08:33:20 AM »

I have an application that is an interface to a single session service device - actually and EFTPOS device.

The interface to the EFTPOS is a RTC Server.

This means that only one client can have control of the RTC Server at any one time.

There are many potential RTC Clients that communicate with the RTC Server.

The approach I have taken is:
 - for the RTC Server is MultiThreaded = False and Blocking = True
 - for the RTC Client is MultiThreaded = False and Blocking = True

There are, however, a number of processes that may be triggered (by the ETFPOS) that must be sent by RTC Server to the connected RTC Client. I do not want to disturb or interfere with the RTC Client "result" thread.

The process I am favoring to implement is to have a second RTC Client component through which these Server-triggered messages will be processed.

Is there a better approach I should consider?

TIA

Zane
 
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #1 on: February 22, 2012, 09:52:55 AM »

Hi Zane,

You don't have to set the Blocking property to TRUE on a TRtcHttpServer, if you just want to disallow automatic creation of background threads by that component. It is enough to set the MultiThreaded property to FALSE (default setting).

By setting the "Blocking" property to TRUE in a Windows Server Application using the TRtcHttpServer component, you are changing from asynchronous WinSock API, which can handle any number of connections from a single thread, to a blocking WinSock API, which needs to create at least one background thread for the socket listener and to wait for incomming data in a non-blocking manner, without forcing you to manually call a procedure in your own code and give you the appearance of using asynchronous communication.

If you are asking now why the TRtcHttpServer has the "Blocking" property, I've added it so I could test how the components would behave on non-Windows platforms (like MacOSX, Linus and iOS), where asynchronous WinSock isn't available.

Setting the "BLocking" property to TRUE on the TRtcHttpClient component, on the other hand, doesn't create any background threads, because all requests from a single Client connection can be handled using the thread from which you are actively sending out requests.

As for your specific requirements, where one part of your Server requires that only one Client has access to a specific resource at any given time (EFTPOS), while having other Clients which might want to do something else and should not be left "hanging" when that specific resource is being accessed, I think a better solution than using "MultiThreaded=False" would be to "synchronize" access to that specific resource (ETFPOS) by using a critical section, forcing all code using that "one-thread-at-a-time" resource to be accessed from a single thread at a time, even in a multithreaded environment.

Then, you could have each Client open a separate connection to the Server (using a 2nd TRtcHttpClient component) and have the Server use "Delayed Calls" to handle Server-triggered messages.

Best Regards,
Danijel Tkalcec
Logged
zsleo
RTC Expired
*
Posts: 80


« Reply #2 on: February 22, 2012, 10:39:47 AM »

Thanks Danijel.

I see the points WRT Server Side setup.

What I need to do is restrict only one Client to be connected at a time and reject all other Client connection. I think setting "RTC_SERVER_ACCEPT_LIMIT := 1;" should achieve this requirement. To overcome the "hanging" I have implemented a "Try Again" routine in the Client.

This way all other standard and normal RTC setting / operation will be fine.

On the Client, and presume I use RTC_SERVER_ACCEPT_LIMIT = 1, will a connect request from a second RTCHTTPClient be rejected?

Regards
Zane
Logged
zsleo
RTC Expired
*
Posts: 80


« Reply #3 on: February 22, 2012, 10:42:32 AM »

P.S. to the last post.

If blocking were implemented at the RTCClientModule then my problem would be more easily resolved (grin)

Regards
Zane
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #4 on: February 22, 2012, 12:43:34 PM »

1) Why would you need to limit the number of active connections on the Server and refuse further connections? By doing this (especially by changing the global "RTC_SERVER_ACCEPT_LIMIT" variable), a single client opening a connection to the Server will block the Server for all further Clients - until it disconnects itself from the Server. This is, IMO, a very bad design decision for a Server.

I thought you only need to make sure that 1 remote function call will be "in execution" at any given point in time. This can either be achieved by usng critical sections (best solution IMO, because it is meant for exactly these kind of a scenario), or by setting MultiThreaded and Blocking to FALSE on the Server.

2) You can use the "Execute" method with TRtcClientModule if you want to block the Client until a response comes from the Server, but I'm not sure why this would matter to the Server. It is only relevant on the Client side. A single Client, using a single physical TRtcHttpClient component, will always be sending remote calls serialized to the Server. There can never be more than 1 call from a single client at the same time on the Server.

Best Regards,
Danijel Tkalcec
Logged
zsleo
RTC Expired
*
Posts: 80


« Reply #5 on: February 22, 2012, 10:56:04 PM »

Danijel,

If this is inappropriate in this form please remove it but I will attempt to explain with a simple scenario.

1 x Server - an EFTPOS Device
2 x Clients - Sales Desks

Both Clients software application uses the same EFTPOS Device.

2 customers present - one at each Sales Desk.

Reason for "RTC_SERVER_ACCEPT_LIMIT": Both Sales Desks request to use the Server (through the Client) at the same time but only one must get control of the Server and the other Client is rejected with "Try Again". I know there are other methodologies to implement this

I agree that "blocking" is to be removed. The reason I need multiple RTCHTTPClients and why more than Critical sections are required

To keep it simple,
- The Client that gets control of the Server now requests the Server process a payment
- The EFTPOS is now "in control" and sends status and other messages (Server to Client)
  -- These MUST not (other than by the Client) interfere with the original Client payment request
- Through the Server the EFTPOS status and messages may be or may not be responded to by the Client but the client MUST have parallel control of the EFTPOS through the Server
  -- so every EFTPOS status message and every EFTPOS "OK" and "CANCEL" key must be returned to the Client

There is a Server process timeout if the Client does not signal process completed.

Regards

Zane
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #6 on: February 23, 2012, 12:53:15 AM »

Since it is acceptable for the Client to receive a "failed attempt" response from the Server, I would suggest using a global boolean flag variable (like "SomebodyUsingEFT") to signal when someone is using the EFTPOS system and use a critical section variable (like "EFT_CS") to enclose the code part checking if someone is currently using EFTPOS.

Here is a preudo-code example of the "OnExecute" event for a remote function trying to use the EFTPOS, which should make it more clear what I mean:

procedure ...
  var
    ReadyToGo:boolean;
  begin
  // Set local "ReadyToGo" variable to TRUE if we may use EFTPOS ...
  EFT_CS.Acquire;
  try
    if NOT SomebodyUsingEFT then
      begin
      SomebodyUsingEFT:=True;
      ReadyToGo:=True;
      end
    else
      ReadyToGo:=False;
  finally
    EFT_CS.Release;
    end;

  if NOT ReadyToGo then
    begin
    { Somebody is already using EFTPOS.
      We should respond to the Client and let him know the Server is busy.
      The Client should then wait for a while (maybe 1 second) before trying again. }
    Result.asException:='ETFPOS busy. Try again later.'
    end
  else
    begin
    try
      { Nobody else was using EFTPOS when this remote call arrived,
        so we have set the "SomebodyUsingEFT" variable to TRUE and
        can now safely use EFTPOS and send a response when done. }
      ProcessEFTRequest;
    finally
      {  Make sure to reset the "SomebodyUsingEFT" flag before exiting. }
      SomebodyUsingEFT:=False;
      end;
    end;

Naturally, the Client side also needs to be implemented to understand what "Result.isType=rtc_Exception" means, so it can send a new remote call to the Server if the initial call failed because EFTPOS was in use.

As a result of this implementation, the Server can be MultiThreaded, the Server can accept any number of client connections and the connections can remain active even if nothing is being sent/received, and the Client (or more of them) which doesn't get access to EFTPOS will get a response from a Server instead of simply being disconnected or refused to connect.

Best Regards,
Danijel Tkalcec
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.026 seconds with 17 queries.