[Lazarus] lnet component

Bernd prof7bit at gmail.com
Wed Sep 5 11:05:53 CEST 2012


2012/9/5 Antonio Fortuny <a.fortuny at sitasoftware.lu>:

> Question: how to suspend the application while waiting for either a
> connection or a response from the server ? In other words, how to run lnet
> in a synchronous way (like Indy does) ?

I would use a TTimer and during the timer event check how far your
handshake has proceeded or whether it got stuck somewhere and
disconnect the TLTcp from within this timer event.


# Synchronous mode:

You can easily use LNet in synchronous mode, here is a code snippet
that makes use of this, although I must say I have abandoned this
particular piece of code, I would not do it the same way  again, This
code will establish many client connections to different servers and
use a separate thread for each of them. If I were to do it again I
would use only one network thread for all my TLTcp objects.

A TPeer object inherits from TThread, each TPeer represents exactly
one outgoing connection. I removed some stuff that is not relevant, I
hope I did not remove too much. CallAction is guaranteed to return
after FConn.Timeout whether it is already connected or not, therefore
I made my own timeout counter that simply counts how many times it
returned:

constructor TPeer.Create(PeerAddrV4: String; PeerPort: Word);
begin
  inherited Create(true);

  FConn := TLTcp.Create(nil);
  FConn.OnDisconnect := @OnDisconnect;
  FConn.OnReceive := @OnReceive;
  FConn.OnError := @OnError;
  FConn.OnConnect := @OnConnect;

  log('trying %s:%d', [PeerAddrV4, PeerPort]);
  FConn.Connect(PeerAddrV4, PeerPort);
end;

destructor TPeer.Destroy;
begin
  FConn.Free;
  inherited Destroy;
end;

procedure TPeer.Execute;
var
  TimeoutCounter : Integer = 3; // ~seconds
begin
  FConn.Timeout := 950 + Random(100);
  repeat
    if (not FConn.Connected) and (TimeoutCounter = 0) then begin
      log('conection timeout (%s)', [PeerAddress]);
      FConn.Disconnect(True);
      Terminate;
    end else begin
      Dec(TimeoutCounter);
    end;
    try
      FConn.CallAction;
    except
      // this is not supposed to happen. No exception should
      // propagate up to this point. This must be a bug!
      LogException('BUG: during CallAction()');
    end;
    {$ifdef HEAPTRC}DumpHeap;{$endif}
  until Terminated;
  log('peer thread terminated (%s)', [PeerAddress]);
  FCanFree := True;
end;

If you want to have multiple TLTcp using the same thread then you must
create only one Thread and one separate TLSelectEventer and assign
this eventer to each of your TLTcp objects. Then you call the
CallAction() method directly on the eventer itself instead of calling
TLTcp.CallAction().

Its actually quite simple. LNet with its pluggable eventers is a
brilliant piece of code (the core units at least) and its incredibly
small and flexible :-)




More information about the Lazarus mailing list