Recent

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

jolix

  • Jr. Member
  • **
  • Posts: 60
multisocket with lnet component - how do this
« on: June 29, 2010, 07:20:00 pm »
Hi,

Solved questions posted on this forum, is time to next war.

My application should open and talk with until maximum 32 sockets (32 different IP) each one is an tcp server electronic module.
Those modules are placed in different places in my home and my garden.

This amount of different sockets are to much to have 32 software modules, so the ideal is to have some sort of index for access those modules in circular way.

Someone in this forum with knowledge enough is capable to elucidate me about it?
Can i do it with LNet ?

Thanks in advance

Jo

Almindor

  • Sr. Member
  • ****
  • Posts: 412
    • http://www.astarot.tk
Re: multisocket with lnet component - how do this
« Reply #1 on: July 03, 2010, 03:23:44 pm »
Do I understand it right that you need 32 separate servers? If so you can make an array or list of them. You can still use the "visual" ones (if you use forms) but make sure to assign the form as parent otherwise it won't work. You can share the event callbacks on them too, just make sure to use the aSocket parameter to handle replies etc.

jolix

  • Jr. Member
  • **
  • Posts: 60
Re: multisocket with lnet component - how do this
« Reply #2 on: July 04, 2010, 02:33:14 pm »
Before anything else, many thanks Almindor.

Back to the topic, yes, you have understood right, i have 32 TCP/modules with an unique IP/Port for each one.
Additionally, i can configure destination IP/Port that is the IP of my PC.

You have made some suggestions that i understand  it formally but not in practice, because my experience is on microcontrollers, not pc software.

So how do i index sockets as you are you suggesting?, taking in account that all modules and consequetly, all sockets must remain open.

About assign form as parent, since i work in the main form, is implicit that is parent!?

Regards,
Joli

Almindor

  • Sr. Member
  • ****
  • Posts: 412
    • http://www.astarot.tk
Re: multisocket with lnet component - how do this
« Reply #3 on: July 05, 2010, 11:25:05 am »
Ok, before we go any further I need to know why you need 32 separate servers and not 1 server with 32 sockets in it.

Do you need different port for each of the incoming connection? If you need 32 connections on same port then you're mixing things up a bit, and just need one server with 32 sockets in it. If that's the case then all you have to do with lNet is use the OnAccept event and "store" the socket (from the aSocket parameter in the procedure) into some list with some sort of identifier (you can use a TStringList.Objects or other lists/maps for this).

If you really need 32 different ports opened then you need 32 TLTcp servers listening on them, best is to use an array. Specify what you need first tho before we get into code.

jolix

  • Jr. Member
  • **
  • Posts: 60
Re: multisocket with lnet component - how do this
« Reply #4 on: July 05, 2010, 03:24:43 pm »
Hi Almindor,

Quote
Ok, before we go any further I need to know why you need 32 separate servers and not 1 server with 32 sockets in it.

Instead of trying to explain things for wich i'm very green, perhaps is more interesting to describe the system.

For instance, in different places of my home, i will have tcp/ip modules to collect the temperature.
Additionally, each one have one output to control air conditioner equipment (on/off).

Each module is configured as a server and have one ip/port that i can modify.
Through this socket, my program sends commands to inquire what temperature is or send commands to tell the module turn on/off air conditioner.

Additionally, i can configure on each module the ip of my pc and port by wich the program will receive or listen.

Even before test, because right now i have just one module, as a result of module beaviour, i suspect that i can have all modules with the same ip but with different ports.
I will have shure about it, just in a few days from now.

The question you put about, why not configure modules as a client, well is my program that allways assumes the iniciative in terms of stablish connection and communication too.
My module just acepts connections and commands from my pc.
Working like this i though the module is server. Tell me if i'm wrong.

Regards,
Jo



jolix

  • Jr. Member
  • **
  • Posts: 60
Re: multisocket with lnet component - how do this
« Reply #5 on: July 06, 2010, 01:13:13 pm »
Just one more thing in addition to my last post 5 July.

The modules i talk about, doesn't support way to initiate connections, but only acepts connections requests from PC.

Regards,
Jo

JohnvdWaeter

  • Full Member
  • ***
  • Posts: 171
    • http://www.jvdw.nl
Re: multisocket with lnet component - how do this
« Reply #6 on: July 06, 2010, 01:34:37 pm »

Than I read it as you have 32 little servers and you want one client to collect data from these 32 servers, right?

Next, do the servers only send data when requested to?

In that case you'll need only one tcpclient that
for each little server
 1: sets ipnr and port
 2: opens a connection
 3: request data
 4: close connection


If, for whatever reason, you want to keep the connections open, you'll need 32 tcpclients....

John


Almindor

  • Sr. Member
  • ****
  • Posts: 412
    • http://www.astarot.tk
Re: multisocket with lnet component - how do this
« Reply #7 on: July 06, 2010, 05:26:09 pm »
As JohnvdWaeter said :)

If you really need 32 connections open in parallel you can use an array. Just don't forget to assign the parent property (use your form) and the events (you can share these if you want, e.g. just one procedure for receive events for all 32 clients).

jolix

  • Jr. Member
  • **
  • Posts: 60
Re: multisocket with lnet component - how do this
« Reply #8 on: July 07, 2010, 05:57:52 am »
JohnvdWaeter, the answers to your questions is yes.

Follow what you suggest, the only step i want to avoid, is the last one (Close Connection).

To write the code for 32 clients i will need drag 32 tcp components to my form, or just enough one and declare 32 different names ?

type
        MyTcpSocket1: TLTCPComponent;
        MyTcpSocket2: TLTCPComponent;
        // next 3 to 31 socket declarations
        MyTcpSocket32: TLTCPComponent;
end;

To use arrays as Almindor said, wich is without doubt more elegant, i don't know how to do it.

You know any internet location where i can find one example? or maybe just a site where this question is discussed?

Thanks by your help
Jo

JohnvdWaeter

  • Full Member
  • ***
  • Posts: 171
    • http://www.jvdw.nl
Re: multisocket with lnet component - how do this
« Reply #9 on: July 07, 2010, 09:27:35 am »
Almindor certainly will know the best solution using an array of tcpcomponents.

Every little server has his own ipnr and portnumber (on which it listens for incoming connections). ipnrs are different to each server, ports can be different but may be the same.

Would be nice if the last part of the ipnr identifies the server. So, for example, for the servers you use 192.168.2.101 ... 192.168.2.132.

In the common OnReceive-event you will know from what server the answer comes by checking the last two digits of the asocket.peeraddress.

On the other hand, if this is a local network, I would not bother to use TCP but rather use connectionless UDP. This saves you the trouble programming around sudden disconnections (like power-problems, cable disconnected etc). And a single TUDPcomponent would be enough if your client polls all the servers. But that all depends on your network, the possibility of using UDP on the little servers and the frequency that you want the data to be read (every 10 milliseconds? once a minute? once an hour?).

John


jolix

  • Jr. Member
  • **
  • Posts: 60
Re: multisocket with lnet component - how do this
« Reply #10 on: July 07, 2010, 02:31:18 pm »
Hi JohnvdWaeter,

Yes, what i'm doing is exactally coincident with what you said.
About ip segment, it is the same for server and client, because both is on the same local network.

UDP is nothing not crossing my mind already, maybe with some compared advantages.
I only have to modify the microcontroler firmware to be shure data is sent right.
One additional advantage is that udp supports broadcasts wich is an interesting feature.

Back to the TCP, the interval beetwen data packages will be, never less than 2 seconds.

Sharing the Onreceive event is a thing i understand, but i still need array of tcpcomponent, right? and is the only way i have to know who send data!?

About array of tcpcomponents, i realize that i should go several years back and try to renew forgoten things. Note that in my times, only a few guys talk about object oriented programming, borland turbo pascal 5.

Mean while i hope Almindor give me some help on this.

Thanks,
Jo



JohnvdWaeter

  • Full Member
  • ***
  • Posts: 171
    • http://www.jvdw.nl
Re: multisocket with lnet component - how do this
« Reply #11 on: July 07, 2010, 03:00:22 pm »
I still think UDP is the way to go, no problems with connect/disconnect/arrays etc. A single UDP-server with a single onReceive-event will do.

But if you use TCP and want to stay connected, then yes, you will need 32 tcpclients, in an array or not.

If in an array, use someting like (by head, not tested):
Code: [Select]
var
  MyTCP = array [1..32] of TLTCPComponent;

....
....

for n:=1 to 32 do
 begin
  MyTCP[n]:=TLTCPComponent.create(nil);
  MyTCP[n].OnReceive := @MyReceive;
  ...
  ...
 end;


After this you can use them as MyTCP[n].connect, MyTCP[n].send etc

John

jolix

  • Jr. Member
  • **
  • Posts: 60
Re: multisocket with lnet component - how do this
« Reply #12 on: July 07, 2010, 04:54:35 pm »
Hi JohnvdWaeter,

This is exactly what i need. I will test it imediatly and let you know.

But once I have more than one module, i will do real tests.

I'm very grateful for your help.

Regards,
Jo

Almindor

  • Sr. Member
  • ****
  • Posts: 412
    • http://www.astarot.tk
Re: multisocket with lnet component - how do this
« Reply #13 on: July 10, 2010, 02:02:41 pm »
Don't forget that if you use visual lNet you need to parent the component too like so:

MyClient.Parent := FormMain; // put main form as parent of my component

You can also use the form in .Create so when you close the form you free the network components ;)

Tell us how it went.

jolix

  • Jr. Member
  • **
  • Posts: 60
Re: multisocket with lnet component - how do this
« Reply #14 on: July 10, 2010, 07:07:59 pm »
Hi,

JohnvdWaeter and Almindor,

I'm struggling with this and i'm not getting the expected result.

First:
var
  MyTCP = array [1..32] of TLTCPComponent;
The compiler give me error. It only accepts:
var
  MyTCP : array [1..32] of TLTCPComponent;

Like that, compiler do the job without errors but app give a runtime error when it start in a message box:
Project socket raised exception class "EClassNotFound" with message:
Class "TLTCPComponent" not found


Next, after click on OK button:
Execution stopped
procedure fcp_riseexception


Finally opens LResources unit, pointing to a line where the problem is:
Code: [Select]
    try
      //DebugLn('Form Stream "',ClassType.ClassName,'"');
      //try
      DestroyDriver:=false;
      Reader := CreateLRSReader(Stream, DestroyDriver);
      try
        Reader.ReadRootComponent(Instance);
      finally
        Driver := Reader.Driver;
        Reader.Free;
        if DestroyDriver then
          Driver.Free;
      end;
This code block is part of "function InitLazResourceComponent(Instance: TComponent;"

Almindor ,
Where is supposed to place MyTCP.Parent := TfrmMain ? considering the code below, that certainly is not correct.

Code: [Select]
unit main;

{$mode objfpc}{$H+}

interface

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

type

    { TfrmMain }

    TfrmMain = class(TForm)
        btnConnect: TButton;
        btnDisconnect: TButton;
        ebxIP: TEdit;
        ebxPort: TEdit;
        GroupBox1: TGroupBox;
        gbxCommands: TGroupBox;
        Timer1: TTimer;
        procedure btnConnectClick(Sender: TObject);
        procedure btnDisconnectClick(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;

const
    CR = #13;
    LF = #10;
    CRLF = CR + LF;

implementation

Constructor TfrmMain.Create(TheOwner: TComponent);
var
    x: integer;
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;
end;
end;

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

Please remember my oop knowledges is very rude.

I have one program with only one socket running fine with LNet.

Regards,
Jo

 

TinyPortal © 2005-2018