Jump to content

Moving from VCL to ExtJs application


Rav

Recommended Posts

Hello,

I have two apps, a client VCL app and a server none-VCL app which work together exchanging data using TidTCPClient and TidTCPServer components on both sides. If one side wants to change the other it sends data in a way like this:

  with TidTCPClient.Create do
    try
      try
        Host := 'localhost';
        Port := 1234;
        ReadTimeout := 2000;
        Connect;
        with Socket do
        begin
          write(integer(1));
        end;
        Disconnect;
      except
      end;
    finally
      Free;
    end;

It works simple and reliable. How to properly organize this two way communication using UniGui? Which components should I use?

 

Link to comment
Share on other sites

On the client side the events are triggered by interacting with controls.

On the server side the events are triggered internally, without human intervention.

 

In other words the clients display some server info and can modify some server parameters remotely.

When the server parameter is changed (it could be also done due to other internal reasons) the server sends

a message (delphi record) to all clients, they receive it and update the display info accordingly.

 

Now this scheme works using TidTCPClient+TidTCPServer components bundle on the clients and the server (TidTCPClient

sends a message, TidTCPServer handles received messages).

 

I want to move from VCL to UniGui and use http for exchanging messages.

Link to comment
Share on other sites

In other words the clients display some server info and can modify some server parameters remotely.

When the server parameter is changed (it could be also done due to other internal reasons) the server sends

a message (delphi record) to all clients, they receive it and update the display info accordingly.

 

 

By default web servers can't send messages to (all) clients. Servers can only answer a request.

 

So you can do one of the following;

 

- using TUniTimer (client (browser) sends every x seconds a request for updates to the server)

 

- using "web sockets" (HTML5)

 

- using "long polling" (see here)

Link to comment
Share on other sites

- using TUniTimer (client (browser) sends every x seconds a request for updates to the server)

 

I think it's the best way

 

- using "web sockets" (HTML5)

 

It's too modern way

 

- using "long polling" (see here)

It's too complicated way.

 

Suppose I use TUniTimer. Sorry for the following stupid questions, but there is no UniGui documentation and "all features demo" app didn't clear up the situation either.

1) How to send a message (Delphi record) from a client to the server?

I found a code sample:

UniSession.SendResponse('New Text', False)

Is it the way how the client sends a text message to the server?

2) How should the server handle it?

If found OnHTTPCommand event handler. Is that it?

3) How to send a Delphi record from a client to the server?

UniSession.SendStream?

4)How should the server handle incoming stream?

There is no OnStream event handler.

5)How should the client retrieve new data from the server?

I don't use databases. All data are in the server's memory.

 

As I said I could not find a simple example which shows how to organize this client-server functionality properly.

Link to comment
Share on other sites

you must think, that each unigui session, is like a one vcl running application.

Each unigui session , ( main module or your unigui main form ), can have her custom tcp client, and you can comunicate it like a vcl application, with your custom server.

Link to comment
Share on other sites

Hi Rav, 

 

 honestly do not understand the problem.
 
If you want to communicate with a  TCP server  from  a Unigui Application , just add the  Indy component  IdTcpClient to Unigui Form.
 
 
In my example, I talk to a TCP server that processes a PDF file into a text file and returns to the  Tcp_Client a return code. 
 
 
 
Function Pdftotext(PdfFilename,TextFilename,pdftotextpgm:string) : integer ;
begin
    fuserform.Idtcpclient.Host := tcpserver ;
    fuserform.Idtcpclient.Port := TcpPort ;
   
    Fuserform.IdTCPClient.Connect;
    parms := pdftotextpgm + ';' + pdffilename + ';' + textfilename ;
   
 
    Fuserform.IdTCPClient.IOHandler.WriteLn(parms, TIdTextEncoding.Default);
    result :=  strtoint(   Fuserform.IdTCPClient.IOHandler.ReadLn());
 end; 
 
 

post-1298-0-18195000-1434537012_thumb.png 

 

 

Let me know if you need an example of the code for the Server-TCP

 

 

 

Regards

Link to comment
Share on other sites

Each unigui session , ( main module or your unigui main form ), can have her custom tcp client, and you can comunicate it like a vcl application, with your custom server.

 

If you want to communicate with a  TCP server  from  a Unigui Application , just add the  Indy component  IdTcpClient to Unigui Form.

Yes I tested idTCPClient, it works fine, thank you!

Then I decided to try idTCPServer on the client side and tested the code:

procedure TMainForm.UniFormCreate(Sender: TObject);
begin
  idServer := TIdTCPServer.Create;
  idServer.OnExecute := idServerExecute;
  idServer.DefaultPort := 12345;
  idServer.Active := True;
  UniLabel2.Caption := 'Test';//Works fine
end;

procedure TMainForm.idServerExecute(AContext: TIdContext);
var
  i: integer;
begin
  with AContext.Connection.Socket do
    try
      i := ReadLongint;
      UniLabel2.Caption := inttostr(i);//Exception
    except
    end;
end;

This code gives an exception "Attempt to access nil session reference" while referencing UniLabel2. Why is that?

I guess this relates to the fact that idServerExecute is executed by Indy in a thread, but why "session is nil"?

And another question, VCL components are not thread safe, is the situation the same with UniGui controls?

Link to comment
Share on other sites

don't use a tcpserver in unigui , becouse each user that open new web session, need tcp a server diferent port.

with tcpclient you cant send and recive data.

 

and yes, tcpserver.onexecute, is multithreaded, you can not  access unigui components in the execute method, or in a thread

when you recive data, add data to temporaly buffer, and check and read the buffer content it in unitimer.

Procedure  TmainForm.Oncreate(....)
Begin
 Buffer:=TmemoryStream.create;
End;

procedure TMainForm.idServerExecute(AContext: TIdContext);
var
  i: integer;
begin
  with AContext.Connection.Socket do
    try
      ReadStream(buffer,-1);
    except
    end;
end;

Procedure on unitimer(.....)
Begin
    Buffer.Position:=0;
    i:=buffer.readint;   
    buffer.clear;
    UniLabel2.Caption := inttostr(i);
End;
Link to comment
Share on other sites

  • 2 weeks later...

The TUniTimer works fine, thank you.

But I got another question. As far as I understand the TUniTimer being placed on the main form is instantiated in every session, so with the 100 open sessions we'll have 100 timers on the server side. Is this the right way of constructing the application?

Link to comment
Share on other sites

As far as I understand the TUniTimer being placed on the main form is instantiated in every session,

Yes.

 

so with the 100 open sessions we'll have 100 timers on the server side.

No. TUniTimer runs/fires on client side (browser). But for every "onTimer" the browser sends a request to ther server. So you have very much network trafffic and the server must handle all these requests.

 

Is this the right way of constructing the application?

In my opinion: No. See option 2 and 3 in Post #4.

Link to comment
Share on other sites

See option 2 and 3 in Post #4.

I looked through your long polling application, very informative, thank you!

I think that's a little bit complicated scheme, does it have flaws?

Are you planning to add WebSockets example to it?

Link to comment
Share on other sites

Rav, on 02 Jul 2015 - 11:33 PM, said:

I looked through your long polling application, very informative, thank you!

I think that's a little bit complicated scheme, does it have flaws?

There are 347 downloads - and no bug reports till now...

 

Rav, on 02 Jul 2015 - 11:33 PM, said:

Are you planning to add WebSockets example to it?

No.
Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...