Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Indy Components

Status
Not open for further replies.

00thaphay

Technical User
Feb 25, 2005
6
GB
Hi im having an annoying problem.

Im making a client-server app using indy componenets idtcpclient and idtcpserver naturally.
I should say im a fairly new user to delphi and very new to using indy components so please bare with me if i act a noob.
After browsing throught the indy demos i started my app.

To check for new data on the socket i use a timer that reads the socket every second like so, i saw the technique used in a demo:


procedure TFrmJoin.TimerDatainTimer(Sender: TObject);
Var Inputdata: string;
begin
if not idtcpclient.Connected then
exit;

Inputdata := idtcpclient.ReadLn('',5);
If inputdata <> '' then
begin
If Inputdata[1] = 'C' then
lstchat.Items.Add(HostPlayer+': '+Inputdata);
if Inputdata[1] = 'P' then
begin
frmjoin.Caption := 'Playing Game with - '+Inputdata;
Hostplayer := Inputdata;
end;
end
end;


After it reads whats on the socket it then freezes. However the demo which uses exactly the same technique doesnt freeze. Just wondering if someone could help me out :) The if statements just determine what kind of data the string is, P for playername C for chat.

p.s. demo code:

procedure TForm1.Timer1Timer(Sender: TObject);
var
Com,
Msg : String;
begin
if not IdTcpClient1.Connected then
exit;

Msg := IdTCPClient1.ReadLn('', 5);

if Msg <> '' then
if Msg[1] <> '@' then
begin
{ Not a system command }
memLines.Lines.Add(Msg);
end
else
begin
{ System command }
Com := UpperCase(Trim(Copy(Msg, 2, Pos(':', Msg) -2)));
Msg := UpperCase(Trim(Copy(Msg, Pos(':', Msg) +1, Length(Msg))));
if Com = 'CLIENTS' then
lbClients.Items.CommaText := Msg;
end;

end;
 
00Thaphay:

I don't see any inherent problem as the code is almost identical to the demo, however:

What is the value of your timer in Milliseconds? If this timer is short (mine are always 250 MS give or take) then you should do the following:

Code:
Procedure TForm.Timer1Timer(Sender:TObject);
Var
 yada
Begin
  Timer1.Enabled := False;
  :
  : Your code
  :
  Timer1.Enabled := True;
End;

I have found that multiple events can occur and without the disable you have x**3 interupts hanging out there ..

Regards and HTH,
JGS
 
Hey thanks for reply. My timer is running slower than the demo code. mine is 1000 interval theirs 500.
 
Ok i broke the code down to see exactly where it freezes.

I changed timer to every 5 seconds and put messages everywhere telling me during runtime exactly what it was doing. It freezes when executing the following line when their is no data on the socket:

Inputdata := idtcpclient.ReadLn('',5);

Shouldn't it timeout after 5 seconds ?

 
00thaphay:

The help states:

const ATimeout: integer = IdTimeoutInfinite

Time-out in milliseconds. Default value IdTimeoutInfinite. (-2)

:
:
Use a custom time-out (ATimeout) value to change the number of milliseconds to wait for a response from the peer connection before a time-out occurs. The default value for ATimeout is IdTimeoutInfinite. See IdGlobal.pas for more information on constant timeout values.

ReadLn will return an empty string ('') if the peer connection is prematurely closed or a time-out occurs. When a timeout condition occurs in ReadLn, the ReadLnTimedOut property is set to True.


So the answer to your question is "No, it should not timeout in 5 seconds, it should timeout in 5 milliseconds"

That may be too short of an interval based on what is being used as a timer. Change it to 500 (.5 sec) and see if your results change.


Regards and HTH,
JGS
 
Thanks for helping. Unfortunately it did now prevent the freeze :(

I really can't see the problem :( Can it be my server side code? thats simply:

procedure TFrmHost.IdTCPServerConnect(AThread: TIdPeerThread);
begin
lstchat.Items.Add('Client Connected');
athread.Connection.WriteLn('P'+HostPlayerName);
athread.Connection.WriteLn('CWelcome to Server');
end;

The C and P are packing constants used to tell the client/server what type of data it is receiving.
 
00thaphay:

I don't know if this will work, but it won't take long to try.

Basically if ReadLn isn't timing-out, the only way I know to make it not "wait" is by setting the socket to non-blocking.

This MAY do it... put this code in your timer event prior to the readln and give 'er a shot.

Code:
procedure TForm1.Timer1Timer(Sender: TObject);
Var
  Socket1 :  TSocket;
  NoBlocking : Longint;
begin
  Socket1 := idtcpclient1.Binding.Handle;
  NoBlocking := 1;
  IOCtlSocket(Socket1, FIONBIO, NoBlocking);
  idtcpclient1.ReadLn('', 5)
end;


Regards and HTH,
JGS
 
00thaphay:

Forgot to mention you'll need WinSock in the uses list.

JGS
 
Thanks for taking time to help me.

Remebering that im still new lol there isnt a bindings property for idtcpclient.

All i can assign to an integer like NoBlocking is BoundPortMax,BoundPortMin and Boundport

Regards Gary
 
Gary:

Does your code typed in like mine not compile???

Mine compiles...

AND,

The help said that TIdTCPClient is a derivative of TIdTCPConnection which has Binding in it.

If you wouldn't mind.... just stick the code in there and tell me what happens, no compile, Address exception or???

If it doesn't compile, what version of Delphi do you have?

Regards,
JGS

PS I'm going to be on a plane to Hawaii tomorrow so I won't be able to get back to you until Tuesday sometime.
 
Compile error saying Undeclared identifier 'Binding'.

Im using delphi 7.
 
00thaphay,

looks like you're using an old version of Indy. D7 came with version 8. version 10 is the current version.

you can find it at :


--------------------------------------
What You See Is What You Get
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top