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

www.cryer.info
Managed Newsgroup Archive

Re: IdTCPServer

Subject:Re: IdTCPServer
Posted by:"Remy Lebeau (TeamB)" (no.spam@no.spam.com)
Date:Thu, 8 Jun 2006 17:48:41

"Jamie Dale" <j.dale@turboz.net> wrote in message
news:4488c1bb@newsgroups.borland.com...

> well either way it using an array still allows me to keep all the
> users data and a pointer to the AThread. That means I can find
> their connection and write to it fairly easily.

You don't need to do any of that.

> Imagine if I assigned their info to the Thread data - I'd need
> blank threads for the users that wern't even logged on etc.

No, you don't.  Just access the threads that are already running when
needed.  If a user is not logged in, there would not be any thread at all.

> Using an array makes it a lot easier from my POV.

Only because you don't know any better yet.  There are other ways to store
data more effectively.  For example:

    type
        TMyPeerThread = class(TIdPeerThread)
        private
            WriteLock: TCriticalSection;
        public
            Username: String;
            // other values as desired...
            constructor Create(ACreateSuspended: Boolean = True); override;
            destructor Destroy; override;
            procedure SendToUser(const AUser, AMsg: String);
            procedure SendFrom(const AUser, AMsg: String);
            // other methods as desired...
        end;

    constructor TMyPeerThread.Create(ACreateSuspended: Boolean = True);
    begin
        WriteLock := TCriticalSection.Create;
        inherited Create(ACreateSuspended);
    end;

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

    procedure TMyPeerThread.SendToUser(const AUser, AMsg: String);
    var
        List: TList;
        I: Integer;
    begin
        List := Connection.Server.Threads.LockList;
        try
            For I := 0 to List.Count-1 do
            begin
                with TMyPeerThread(List[I]) do
                begin
                    if AnsiSameText(Username, AUser) then
                    begin
                        SendFrom(Self.Username, AMsg);
                        Exit;
                    end;
                end;
            end;
        finally
            Connection.Server.Threads.UnlockList;
        end;
    end;

    procedure TMyPeerThread.SendFrom(const AUser, AMsg: String);
    begin
        WriteLock.Enter;
        try
            Connection.WriteLn(Format('MSG %s %s', [AUser, AMsg]));
        finally
            WriteLock.Leave;
        end;
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
        IdTCPServer1.ThreadClass := TMyPeerThread;
        IdTCPServer1.Active := True;
    end;

    procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
    begin
        with TMyPeerThread(AThread) do
        begin
            Username := AThread.Connection.ReadLn;
            // other values as desired...
        end;
    end;

    procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
    var
        LLine, LCmd, LUser: String;
    begin
        LLine := AThread.Connection.ReadLn;
        LCmd := Fetch(LLine);
        if AnsiSameText(LCmd, 'MSG') then
        begin
            LUser := Fetch(LLine);
            TMyPeerThread(AThread).SendToUser(LUser, LLine);
        end;
        //...
    end;

> Also, seeing as each thread has access to the array, how can
> I stop it being damaged/corrupted?
> Can you provide any sample codes?

One way would be to stop using an array to begin with.

Another way would be to lock access to the array using a critical section,
which was already suggested to you in an earlier discussion.


Gambit

Replies:

In response to:

www.cryer.info
Managed Newsgroup Archive