Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Jun : 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