Recent

Author Topic: multisocket with lnet component - how do this  (Read 22779 times)

Almindor

  • Sr. Member
  • ****
  • Posts: 412
    • http://www.astarot.tk
Re: multisocket with lnet component - how do this
« Reply #15 on: July 11, 2010, 12:00:21 pm »
Did you add lNet as a required package to your project? See project/project inspector [main menu];.

In the "required packages" part do you see lNetVisual? If not add it (press the "+") and pick it from the "New required" tab (it's in the picklist there if it's installed in lazarus).

This should fix the runtime problem you have. Also see if lNetComponents unit is in the uses section of your main unit (the one with form). If not, add it as well.

Your create code seems fine (you can use TLTcpComponent.Create(frmMain) and can thus omit any freeing of the components at destroy).

As for the parent, you can skip that part, I forgot I "fixed" this in a different way, so no need to bother ;)

jolix

  • Jr. Member
  • **
  • Posts: 60
Re: multisocket with lnet component - how do this
« Reply #16 on: July 11, 2010, 01:31:11 pm »
Hi Almindor,

Answering your questions:
Quote
Did you add lNet as a required package to your project? See project/project inspector [main menu];.
I did. The proof is i wrote a program with a single socket and it works ok.

Quote
In the "required packages" part do you see lNetVisual? If not add it (press the "+") and pick it from the "New required" tab (it's in the picklist there if it's installed in lazarus).
Yes i see it.

Quote
This should fix the runtime problem you have. Also see if lNetComponents unit is in the uses section of your main unit (the one with form). If not, add it as well.
Yes, as you can see in the code posted in my last post.
Code: [Select]
uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  StdCtrls, lNetComponents, lNet, ExtCtrls, ComCtrls;

Quote
Your create code seems fine (you can use TLTcpComponent.Create(frmMain) and can thus omit any freeing of the components at destroy).
What i understand about it is, since the objects are children of the Form wich have a constructor, the destructor frees all objects.

I feel the solution is close, but they are some missed part some where.

Same results with:
Windows Vista
Lazarus 0.9.26
fpc 2.2.2
lnet 0.63

XP Pro
Lazarus 0.9.26
FPC 2.2.2
lnet 0.64

Regards
Jo

jolix

  • Jr. Member
  • **
  • Posts: 60
Re: multisocket with lnet component - how do this
« Reply #17 on: July 11, 2010, 04:00:42 pm »
Hi JohnvdWaeter, Almindor,

I decided do a simple test as showed below:

1. I've placed two TCP components on my form.
2. Rename these as, MyTCP1 and MyTCP2 respectively.
3. Assign to both the same tree events:
   - MyReceive to OnReceive event
   - MyConnect to OnConnect event
   - MyDisconnect to OnDisconnect event


Like thus, program works ok.

So, one solution to my case is drag 32 TCP components to my form which is a very stupid thing to do, don't you agree?

What special and different particularity lnet component have that prevents me from creating arrays of objects?

I will try do the John example with buttons to verify if the issue is something related with example method or not.

Additionally, i see on the internet that array of objects can be done with TList also with TObjectList. The question is, i already waste days trying google and seems me that every one uses a simple connection, situation that surprises me.
So, i apologize to you guys to be so bored.

Aware of the work needed to help me, I'll make a Lazarus clone of the server module, to facilitate your help, if you have the kindness and patience to continue.

Regards,
Jo

jolix

  • Jr. Member
  • **
  • Posts: 60
Re: multisocket with lnet component - how do this
« Reply #18 on: July 11, 2010, 04:09:55 pm »
In addition to my last post..

I missed since the begining that OnDisconnect event doesn't work.
All others works fine and i'm surprised since i have doing things right and in the same way for all events, through the object inspector /events Tab.

Regards
Jo

JohnvdWaeter

  • Full Member
  • ***
  • Posts: 168
    • http://www.jvdw.nl
Re: multisocket with lnet component - how do this
« Reply #19 on: July 11, 2010, 04:18:20 pm »
Jolix,

Quote
Note that i suppressed all the code not significant right now.

Maybe... the other code IS more significant than you think it is....

For example, in the OnReceive-event, you MUST read from the socket. If you do not, ondisconnect is not fired either...

I don't see nothing wrong in the declaration and creation of the array.

Note also that you created tcp CLIENTS and that it is a clients task to initiate a connection with a server. Only after that, data can be exchanged.

John

jolix

  • Jr. Member
  • **
  • Posts: 60
Re: multisocket with lnet component - how do this
« Reply #20 on: July 12, 2010, 12:58:40 pm »
Hi JohnvdWaeter,
Code: [Select]
{******************************************************************************
* This is a JohnvdWaeter example to have 32 sockets based on LNet component.
* Almindor is also involved trying to help
*------------------------------------------------------------------------------
* Forum Topic: http://www.lazarus.freepascal.org/index.php/topic,9751.15.html
*------------------------------------------------------------------------------
* Date:      2010/07/11
* Project:   My home Air Conditioner control
* Test Fase: Adquire temperature of one sensor
* Future:    Adquire temperature of 32 sensors with ON/OFF control
* Comms:     Network TCP/IP based
*
* Cliente Software:
*            IDE:       Lazarus 0.9.26
*            Compiler:  FPC 2.2.2
*            O.S.       XP / Vista
******************************************************************************}

unit main;

{$mode objfpc}{$H+}

interface

uses
    Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
    StdCtrls, lNetComponents, lNet, ExtCtrls, ComCtrls;

type

    TfrmMain = class(TForm)
        btnConnect: TButton;
        btnDisconnect: TButton;
        btnGetTemp: TButton;
        btnExit: TButton;
        btnSendACK: TButton;
        ebxIP: TEdit;
        ebxPort: TEdit;
        gbxServer: TGroupBox;
        gbxCommands: TGroupBox;
        lblDebugList: TLabel;
        lblIP: TLabel;
        lblPort: TLabel;
        lbxLog: TListBox;
        StatusBar1: TStatusBar;
        Timer1: TTimer;
        procedure btnConnectClick(Sender: TObject);
        procedure btnDisconnectClick(Sender: TObject);
        procedure btnExitClick(Sender: TObject);
        procedure btnGetPointersClick(Sender: TObject);
        procedure btnGetTempClick(Sender: TObject);
        procedure btnSendACKClick(Sender: TObject);
        procedure MyConnect(aSocket: TLSocket);
        procedure MyDisconnect(aSocket: TLSocket);
        procedure MyReceive(aSocket: TLSocket);
        procedure Timer1Timer(Sender: TObject);

    private

    public
        Constructor Create(TheOwner: TComponent); override;
        procedure FormKill(Sender: TObject);
    end;


var
    frmMain: TfrmMain;
    MyTCP : array[1..32] of TLTCPComponent;
    NewMsg, OldMsg: string;
    constates: integer;

const
    CR = #13;
    LF = #10;
    CRLF = CR + LF;
    ACK = '00';
    GET_TEMP = 'AE';

implementation

{******************************************************************************
* Init
******************************************************************************}
Constructor TfrmMain.Create(TheOwner: TComponent);
var
    x: integer;
    s: string;
begin
    inherited Create(TheOwner);
    OnDestroy := @FormKill;

    for x := 1 to 32 do begin
        MyTCP[x] := TLTCPComponent.create(nil);
        MyTCP[x].OnReceive := @MyReceive;
        MyTCP[x].OnConnect := @MyConnect;
        MyTCP[x].OnDisconnect:= @MyDisconnect;
    end;

    NewMsg := '';
    ebxIP.Text := '192.168.2.100';
    ebxPort.Text := '1001';
    btnConnect.Enabled := True;
    btnDisconnect.Enabled := False;
    ebxIP.Color := clScrollBar;
    ebxPort.Color := clScrollBar;
    constates := 0;
end;

{******************************************************************************
* Form Close
******************************************************************************}
procedure TfrmMain.FormKill(Sender : TObject);
begin
end;

{******************************************************************************
* Close by Button
******************************************************************************}
procedure TfrmMain.btnExitClick(Sender: TObject);
begin
    Close;
end;

{******************************************************************************
* Open Connection by button
******************************************************************************}
procedure TfrmMain.btnConnectClick(Sender: TObject);
begin
    constates := 1;
end;

{******************************************************************************
* Disconnect button
******************************************************************************}
procedure TfrmMain.btnDisconnectClick(Sender: TObject);
begin
    if MyTCP[1].Connected then begin
        MyTCP[1].Disconnect;
        btnConnect.Enabled := True;
        btnDisconnect.Enabled := False;
        ebxIP.Color := clScrollBar;
        ebxPort.Color := clScrollBar;
        StatusBar1.Panels[1].Text :=  'Disconnected';
    end;
end;

{******************************************************************************
* Get Temperature button
*------------------------------------------------------------------------------
* Server Module should answer: 'E0XX'+#13#10, where XX teperature in ASCII Hex
******************************************************************************}
procedure TfrmMain.btnGetTempClick(Sender: TObject);
begin
    MyTCP[1].SendMessage(GET_TEMP + CRLF);
end;

{******************************************************************************
* Send Acknowlodge: Server also reply ACK
******************************************************************************}
procedure TfrmMain.btnSendACKClick(Sender: TObject);
begin
    MyTCP[1].SendMessage(ACK + CRLF);
end;

{******************************************************************************
* OnReceive event
******************************************************************************}
procedure TfrmMain.MyReceive(aSocket: TLSocket);
var s: String;
begin
    MyTCP[1].GetMessage(s);
    if Length(s) > 3 then begin
        lbxLog.Items.Add(copy(s,1, Length(s)-2));
        s:='';
    end;
end;

{******************************************************************************
* OnConnect event
******************************************************************************}
procedure TfrmMain.MyConnect(aSocket: TLSocket);
begin
    btnConnect.Enabled := False;
    btnDisconnect.Enabled := True;
    StatusBar1.Panels[1].Text:='Connected to: '+ ebxIP.Text+ ':'+ ebxPort.Text;
end;

{******************************************************************************
* OnDisconnect event
******************************************************************************}
procedure TfrmMain.MyDisconnect(aSocket: TLSocket);
begin
    btnConnect.Enabled := True;
    btnDisconnect.Enabled := False;
    StatusBar1.Panels[1].Text:='Disconnected from: '+ ebxIP.Text+ ':'+ ebxPort.Text;
end;

{******************************************************************************
* Try to Connect state machine
*------------------------------------------------------------------------------
* This state machine is needed because server sometimes hangup and reset it self
* during powerup. This is working well on the 1 socket program version
*------------------------------------------------------------------------------
* Right now number of tries are infinite and just work with MyTCP[1].
* In the future we have finite number of tries for each one connection
******************************************************************************}
procedure TfrmMain.Timer1Timer(Sender: TObject);
var s: string;
begin
    case constates of

        0:  begin
            end;

        1:  begin
                MyTCP[1].Connect( ebxIP.Text, StrToInt(ebxPort.Text));
                constates := 2;
            end;

        2:  begin
                MyTCP[1].SendMessage('00'+ CRLF);
                ebxIP.Color := clAqua;
                ebxPort.Color := clAqua;
                constates := 3;
            end;

        3:  if MyTCP[1].Connected then begin
                ebxIP.Color := clLime;
                ebxPort.Color := clLime;
                gbxCommands.Enabled := True;
                constates := 0;  // Connected. Stop state machine
            end
            else begin
                ebxIP.Color := clScrollBar;
                ebxPort.Color := clScrollBar;
                constates := 1; // Try again
            end;
    end;
end;

initialization
  {$I main.lrs}

end.

Also i can send all files needed to compile, but i don't see how can do it.

Regards,
Jo

jolix

  • Jr. Member
  • **
  • Posts: 60
Re: multisocket with lnet component - how do this
« Reply #21 on: July 12, 2010, 04:01:53 pm »
Hi again,

I tried to do an array of Buttons using the same methodology as for TLTCPComponent and works fine.

So, this leads me to conclude that the component LNET has some peculiarity that prevents creating arrays. At least in the way suggested.

Maybe Almindor wants to say something about it, while author of this component?

Regards
Jo

JohnvdWaeter

  • Full Member
  • ***
  • Posts: 168
    • http://www.jvdw.nl
Re: multisocket with lnet component - how do this
« Reply #22 on: July 12, 2010, 05:29:07 pm »
I did not try your code, but every little server has the same ipnr?
maybe the code is not complete, but they all must have different ipnrs...

And: better show code for all 32 servers. You could pinpoint where the error occurs.

Like, for example:

 try
  tcp[n].connect
 except
  on e:exception do
  showmessage('error on #'+inttostr(n)+', '+e.message)
 end;

John

jolix

  • Jr. Member
  • **
  • Posts: 60
Re: multisocket with lnet component - how do this
« Reply #23 on: July 12, 2010, 07:17:40 pm »
John

My little servers can eventualy have the same ip but different ports.
I'm still waiting for arriving modules.
By now as you can see on the code sent, i only work with one socket, MyTCP[1].

However, before advance to what you suggest, my problem is that my code doesn't even start.
The compiler / debugger behavior is:
"Project xxx created successfull"

After, debbuger i think, lanches this message window:
Project socket raised exception class "EClassNotFound" with message:
Class "TLTCPComponent" not found


After click OK, IDE lanches LResources unit on the editor and points to this line:
Code: [Select]
      try
        Reader.ReadRootComponent(Instance); // <<< DEBUGGER POINTS TO THIS LINE
      finally
This lines are part of procedure FormDataToText(FormStream, TextStream: TStream);,
inside of LResources unit.

This happens just after compilation end and i never see my program form.
I receive a message: Program stops.

I even have commented those lines in my code:
Code: [Select]
    for x := 1 to 32 do begin
        //MyTCP[x] := TLTCPComponent.create(nil);
        //MyTCP[x].OnReceive := @MyReceive;
        //MyTCP[x].OnConnect := @MyConnect;
        //MyTCP[x].OnDisconnect:= @MyDisconnect;
    end;
The result is the same.
So i think the issue have to do with some declaration or LCTCPComponent issue, as i said before, unless i have something wrong in the code.

Remember i test this array of objects with buttons and works.

Regards,
Jo

jolix

  • Jr. Member
  • **
  • Posts: 60
Re: multisocket with lnet component - how do this
« Reply #24 on: July 12, 2010, 08:24:47 pm »
Hi again,

Sorry to come again.
This oop thing is very confused to me yet. (x is y, y as z...)
As showed by the message error mentioned in my last post, the compiler could not instantiate:
Code: [Select]
MyTCP[x]:=TLTCPComponent(nil) if i understand it right.

Now program runs as expected.

Solution:

In the type section:
Code: [Select]
MySocket : TLTCPComponet;
MySocket is the name i given to the component on the Object Inspector.

Inside of form constructor:
Code: [Select]
    for x := 1 to 32 do begin
        //MyTCP[x]              := TLTCPComponent.create(nil); <<<< BAD WAY
        MyTCP[x]              := MySocket.create(nil);  <<<<< GOOD WAY
        MyTCP[x].OnReceive    := @MyReceive;
        MyTCP[x].OnConnect    := @MyConnect;
        MyTCP[x].OnDisconnect := @MyDisconnect;
        MyTCP[x].OnError      := @MyError;
    end;

After "this battle won almost to the last man:)", i just wait for more modules to test more than one socket.
I will test 32 servers with:
- Same IP but different Ports.
- Different IP's but same Port.

When finish, i will notice.

Meanwhile, i would like to thank you very much to you John and Almindor.
Also my apologyses to be so boring.

Regards,
Jo

 

TinyPortal © 2005-2018