Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Oct : Re: TIdTrivialFTPServer and multi-homed server?

www.cryer.info
Managed Newsgroup Archive

Re: TIdTrivialFTPServer and multi-homed server?

Subject:Re: TIdTrivialFTPServer and multi-homed server?
Posted by:"Philippe Auphelle" (pauphelle.no.spam.please@wanadoo.fr)
Date:Wed, 11 Oct 2006 14:26:45

Gambit,

>> At startup, TFTPServer only listen to the first of its bindings.
>
> Not true.  It actively listens on all entries in the
> Bindings collection equally.


Weeeeeeellll...
The Indy I have is a '10.1.5' that I downloaded as a "release" early
December 2005 - I precisely checked.
And the fact is that does it just the way I said, and not the way you
thought it did:

function TIdUDPServer.GetBinding: TIdSocketHandle;
var
   i: integer;
begin
   if FCurrentBinding = nil then begin
     if Bindings.Count < 1 then begin
       Bindings.Add;
     end;
     for i := 0 to Bindings.Count - 1 do begin
{$IFDEF LINUX}
       Bindings[i].AllocateSocket(Integer(Id_SOCK_DGRAM));
{$ELSE}
       Bindings[i].AllocateSocket(Id_SOCK_DGRAM);
{$ENDIF}
       Bindings[i].Bind;
     end;
     FCurrentBinding := Bindings[0];
     FListenerThread := TIdUDPListenerThread.Create(BufferSize, Self);
     FListenerThread.Start;
     BroadcastEnabledChanged;
   end;
   Result := FCurrentBinding;
end;

As you can see,
TIdUDPListenerThread.Create(BufferSize, Self);
is called just once, with FCurrentBindings set to Bindings[0], and a
debugging session shows that this code is called only once, creating a
single thread. The call happens when I set the server active, in
TIdUDPBase.SetActive. And the TIdUDPServer object has room to keep track
of a single TIdUDPListenerThread in FListenerThread, anyway.
Bottom line: That version didn't support multi-homing, except maybe by
running several instances of the server object and passing to each a
different local address.
Ooops.
This behavior precisely matches the experimental facts I reported, BTW.
Facts are stubborn.

Now for the good news!
The latest snapshot (that I haven't tried yet, need to carefully build
and test it first) looks much better, since GetBinding does create one
listener per thread. And FListenerThread is now a TidThreadList, while
it used to be a TIdUDPListenerThread.

The code is a tad longer, but here is the excerpt that I more specially
like:

  for i := 0 to Bindings.Count - 1 do begin
    LListenerThread := TIdUDPListenerThread.Create(Self, Bindings[i]);
    LListenerThread.Name := Name + ' Listener #' + Sys.IntToStr(i + 1);

    LListenerThread.Priority := tpListener;
    FListenerThreads.Add(LListenerThread);
    LListenerThread.Start;
  end;

Aaaaaah!
Evidence found, case closed.

Thanks for (indirectly :) ) pushing me to get to the source.
I learned a few things during that trip, starting with how to properly
handle the LocalAddresses / Bindings issue. /Ph.

Replies:

In response to:

www.cryer.info
Managed Newsgroup Archive