Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Dec : Re: IdTCPServer

www.cryer.info
Managed Newsgroup Archive

Re: IdTCPServer

Subject:Re: IdTCPServer
Posted by:"Remy Lebeau (TeamB)" (no.spam@no.spam.com)
Date:Fri, 29 Dec 2006 12:29:47

"Anders Balslev" <itq@business.tele.dk> wrote in message
news:45957531$1@newsgroups.borland.com...

> When for example 3 client connections are connected to the
IdTCPServer
> (and the TCP Server has detected the IP adresses, IP1, IP2 IP3), how
> can I in the application send "Hello World" to IP2? - and something
else to
> IP3, and something else to IP1

Each client is represented by a TIdPeerThread (Indy 9) or TIdContext
(Indy 10) object within the server.  Simply write whatever you want to
that object's Connection.

> which are NOT responses from the client- all 3 just remains open

TIdTCPServer is a multi-threaded component.  You are supposed to do
your reading and writing for each client inside the OnExecute event,
which is triggered in the context of a worker thread for each client.
However, it does not sound like you are trying to implement a typical
client/server model in the first place.  If your server is never going
to read from a client, only write to it, then you have a couple of
options:

1) put a Sleep() inside the OnExecute event and nothing else (to
prevent high CPU usage) and then use the server's Threads (Indy 9) or
Contexts (Indy 10) collection to directly access each client from
another thread (such as the main thread) when needed.  For example:

    procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
    begin
        Sleep(50);
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    var
        List: TList;
    begin
        List := IdTCPServer1.Threads.LockList;
        try
            TIdPeerThread(List[SomeIndex]).Connection.WriteLn('Hello
World');
        finally
            IdTCPServer1.Threads.UnlockList;
        end;
    end;

Alternatively:

    procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
    begin
        // discard anything the client sends ...
        if AThread.Connection.ReadFromStack(True, 50, False) > 0 then
            AThread.Connection.InputBuffer.Clear;
  end;


2) implement a per-client outbound queue that you can store data in
when needed, and then have the OnExecute event flush the queue to a
client regularly as needed.

    uses
        IdThreadSafe;

    type
        TMyPeerThread = class(TIdPeerThread)
        public
            constructor Create(ACreateSuspended: Boolean = True);
override;
            destructor Destroy; override;
            Queue: TIdThreadSafeStringList;
        end;

    constructor TMyPeerThread.Create(ACreateSuspended: Boolean =
True);
    begin
        Queue := TIdThreadSafeStringList.Create;
        inherited Create(ACreateSuspended);
    end;

    destructor TMyPeerThread.Destroy;
    begin
        Queue.Free;
        inherited Destroy;
    end;

    constructor TForm1.Create(AOwner: TComponent);
    begin
        inherited Create(AOwner);
        IdCPServer1.ThreadClass := TMyPeerThread;
    end;

    procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
    var
        Strings: TStrings;
    begin
        with TMyPeerThread(AThread) do
        begin
            Strings := Queue.Lock;
            try
                Connection.WriteStrings(Strings);
            finally
                Queue.Unlock;
            end;

            // discard anything the client sends ...
            if Connection.ReadFromStack(True, 50, False) > 0 then
                Connection.InputBuffer.Clear;
        end;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    var
        List: TList;
    begin
        List := IdTCPServer1.Threads.LockList;
        try
            TMyPeerThread(List[SomeIndex]).Queue.Add('Hello World');
        finally
            IdTCPServer1.Threads.UnlockList;
        end;
    end;


Gambit

Replies:

none

In response to:

www.cryer.info
Managed Newsgroup Archive