Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Jun : Re: FContextList problems Indy10.1.5

www.cryer.info
Managed Newsgroup Archive

Re: FContextList problems Indy10.1.5

Subject:Re: FContextList problems Indy10.1.5
Posted by:"Jacques" (jacques.no..@btinternet.com)
Date:Mon, 5 Jun 2006 11:00:49

Thanks Remy

Since you have not specified how many clients are actually connected to
your
> server at the time

At least five clients are connected to the server at any given time.

Here's the code:

Server Code
type
TMyContext = class(TIdContext)
        public
            IP: String;
            Nick: String;
            Con: TDateTime;
            procedure SendMsg(const Afrom,ANick: String; const AMsg:
String);
            procedure BroadcastMsg(const bmsg: String);
            procedure BroadcastMsgAll(const ANick: String; const bmsg:
String);
            procedure SendNicks;
           end;


procedure TMyContext.SendNicks;
    var
        List: TList;
        Context: TMyContext;
        I: Integer;
    begin
        List := FContextList.LockList;
        try
            if List.Count > 0 then
            begin
                for I := 0 to List.Count-1 do
                begin
                    Context := TMyContext(List[I]);
                    if Context <> Self then
//Send the list
Connection.IOHandler.WriteLn('list@'+ Context.Nick);
                end;
            end else
                Connection.IOHandler.WriteLn('list@No other members
available.');
        finally
            FContextList.UnlockList;
        end;
    end;

//Here the connecting client details are collected
procedure TForm1.tsConnect(AContext: TIdContext);
    begin
        with TMyContext(AContext) do
        begin
            Con := Now;
            if (Connection.Socket <> nil) then
            IP :=Connection.Socket.Binding.PeerIP;
            Nick := Connection.IOHandler.ReadLn;
            if Nick <> '' then
            begin
                Connection.IOHandler.WriteLn('Welcome ' + Nick + '!');
                BroadcastMsg(Nick + ' just joined!');
                       end else
            begin
                Connection.IOHandler.WriteLn('No Nick provided! Goodbye.');
                Connection.Disconnect;
            end;
        end;
    end;

procedure TForm1.tsExecute(AContext: TIdContext);
var
cmd,str:string;
idx,posi:integer;
begin
//Break up the string sent by client to get the command
str:=acontext.Connection.IOHandler.ReadLn;
posi:=pos('@',str);
cmd:=copy(str,1,posi-1);
  //Nicknames of all connected clients requested...
if cmd='listnames' then begin
TMyContext(AContext).SendNicks;
    end
end;


Client Code:

TReadingThread = class(TThread)
        protected
            FConn: TIdTCPConnection;
            procedure Execute; override;
        public
            constructor Create(AConn: TIdTCPConnection); reintroduce;
        end;
         TLog = class(TIdSync)
        protected
            FMsg: String;
            procedure DoSynchronize; override;
        public
            constructor Create(const AMsg: String);
            class procedure AddMsg(const AMsg: String);
        end;
IMPLEMENTATION

constructor TReadingThread.Create(AConn: TIdTCPConnection);
    begin
        FConn := AConn;
        inherited Create(False);
    end;

    procedure TReadingThread.Execute;
    var
        s: String;
    begin
        while not Terminated and FConn.Connected do
        begin
                     TLog.AddMsg(FConn.IOHandler.ReadLn);
        end;
    end;

class procedure TLog.AddMsg(const AMsg: String);
    begin
       with Create(AMsg) do try
            Synchronize;
        finally
            Free;
        end;
    end;


procedure TLog.DoSynchronize;
    var
    idx,i:integer;
   cmd, thelist:string;
     begin
//FMsg is the string sent by the server you need to break this msg up to
get the
// command,msg and sender name
  //break up msg from server
       idx:=pos('@',FMsg);
//get the command
      cmd:=copy(FMsg,1,idx-1);
//list of names recieved
    if cmd='list' then  begin
   thelist:= Copy(FMsg, Pos('@', FMsg)+1, Length(FMsg)-Pos('@', FMsg));
  //add the names to the listview
form1.lnames.Clear;
form1.li:=form1.lnames.Items.Add;
form1.li.ImageIndex := 15;
form1.li.caption:=thelist;
end
else
form1.msg.Lines.Add(thelist);
    end;

//this how the client request the list of names
procedure TForm1.listnameClick(Sender: TObject);
begin
tc.IOHandler.WriteLn('listnames@fromname');
end;

*****************end code************
A client request the list by sending a string containing a cmd called
'listnames' which as you can see from the Onexecute procedure of the server
code is used to send a list of connected names.

> Indy does have methods available for
> reading/writing TStrings objects.
Can you show how i can use those on the client side? I honestly thought that
the entire list was sent in one go by the server. In future i will have upto
50 connected clients at any one time.  Is there some way of knowing when the
server has stopped sending the names on the Contextlist to the client? Or
perhaps a way that i can change the SendNicks() procedure to send the list
of names bundled up in something similar to a TString object and then sent
off to the client in one go?

Thanks


"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message
news:4483d3a2$1@newsgroups.borland.com...
>
> "Jacques" <jacques.noah@btinternet.com> wrote in message
> news:44823c37$1@newsgroups.borland.com...
>
>> I'm having problems retrieving a list of names of connected clients.
>
> That is because you are not doing it correctly to begin with.
>
>> when the list arrives at the requesting client only ONE of the many
>> client names is shown.
>
> Given the limited code that you have shown so far, there are two
> possibilities:
>
> 1) there is only 1 client in your list to begin with.
>
> 2) the client's reading code is wrong.
>
> Since you have not specified how many clients are actually connected to
> your
> server at the time, or when SendNick() is being called, or shown how the
> client is reading back the list, there is no way to diagnose your problem
> further.  Please provide more details, and more complete code snippets.
>
>> FMsg is the entire 'list' sent by the server
>
> The server is sending the list as multiple strings, but the statement
> above
> suggests that you are processing the list as one big string instead.  The
> code you showed for processing FMsg is not setup for multiple lines,
> unless
> you are calling it in a loop that you have not shown yet.
>
>> Should i be creating a tstringlist to recieve the list on the client
>> side?
>
> That would be a good thing to do, considering that you are sending the
> list
> as multiple strings to begin with.  Indy does have methods available for
> reading/writing TStrings objects.
>
>
> Gambit

Replies:

In response to:

www.cryer.info
Managed Newsgroup Archive