Board index » delphi » Re: Indy demos about the clients

Re: Indy demos about the clients


2004-11-10 06:41:56 AM
delphi74
"Gollup" <XXXX@XXXXX.COM>writes
Quote
Can you provide a little code sample about it ?
You already posted your own example for that.
Quote
Should i set the ReadTimeOut then check for the
EIdReadTimeOut to fire ?
That is one way to do it.
Gambit
 
 

Re: Indy demos about the clients

Should we care about the same situation in server threads too ? Do we need
to do something special like we do for clients for to read and write into
the OnExecute of TIdTCPServer ?
Regards,
"Remy Lebeau (TeamB)" <XXXX@XXXXX.COM>writes
Quote

"Robby Tanner" <XXXX@XXXXX.COM>wrote in
message news:418fbedd$XXXX@XXXXX.COM...

>For the examples that use threads for reading from servers then,
>does the blocking call have to timeout before the thread can
>be terminated/destroyed?

No. During termination, the socket is disconnected. Any blocking calls
will then fail immediately with an exception, and the thread code handles
that accordingly.

>If a thread is destroyed in the middle of a blocking call,
>is everything cleaned up properly?

Yes.


Gambit
 

Re: Indy demos about the clients

I mean do we need to handle read and write separately ?
"Gollup" <XXXX@XXXXX.COM>writes
Quote
Should we care about the same situation in server threads too ? Do we need
to do something special like we do for clients for to read and write into
the OnExecute of TIdTCPServer ?

Regards,

"Remy Lebeau (TeamB)" <XXXX@XXXXX.COM>writes
news:418fc486$XXXX@XXXXX.COM...
>
>"Robby Tanner" <XXXX@XXXXX.COM>wrote in
>message news:418fbedd$XXXX@XXXXX.COM...
>
>>For the examples that use threads for reading from servers then,
>>does the blocking call have to timeout before the thread can
>>be terminated/destroyed?
>
>No. During termination, the socket is disconnected. Any blocking calls
>will then fail immediately with an exception, and the thread code handles
>that accordingly.
>
>>If a thread is destroyed in the middle of a blocking call,
>>is everything cleaned up properly?
>
>Yes.
>
>
>Gambit


 

Re: Indy demos about the clients

My OnExecute code is like this :
ReadRecord;
if ReadedRecord = recMsg then
TriggerMessageReceive;
if ThereIsAMesageToSend then
SendMessage;
When i send a message from the client to server it works fine. But when i
try to send a message from server to client, it just send after the server
receives a message from the client. I mean like that :
Client ->Message("Hello") ->Server
Server gets "Hello"
Server ->Message("Hello Reply") ->Client
Client gets nothing
Client ->Message("Hello Again") ->Server
Server gets "Hello Again"
Client gets "Hello Reply"
I checked this code with breakpoints and i saw that OnExecute triggers and
gets the available message. Then check if there is a message. At the first
time there isn't any message so nothing is sending from server to client.
And when i send an another message from client to server, server receives
the message without to have any problem and see that there is a message to
send this time and send the avilable message from server to client.
OnExecute just running when it is receive a message. I couldn't understand
what is going on. Do you have any idea about it ?
"Gollup" <XXXX@XXXXX.COM>writes
Quote
I mean do we need to handle read and write separately ?
 

Re: Indy demos about the clients

"Gollup" <XXXX@XXXXX.COM>writes
Quote
My OnExecute code is like this :
That is perfectly fine, as long as your reading is not blocking for so long
that your writing does not have an oppurtunity to send queued data in a
timely fashion.
However, as has already been mentioned earlier, if you have a thread that
wants to send data to a socket, there is nothing stopping you from simply
writing to that socket directly immediately. Just make sure that you are
providing adequate synchronization to that socket so that multiple packets
being written will not overlap each other.
Quote
When i send a message from the client to server it works fine.
But when i try to send a message from server to client, it just
send after the server receives a message from the client.
That is because you are probably reading with infinite timeouts so that the
reading does not return until data is actually received. To do what you are
asking, you need to make use of actual timeouts so that the reading stops
reading periodically so that the writing can then proceed when needed.
Gambit
 

Re: Indy demos about the clients

Thanks for your reply. Sorry Remy but i really get confused about it :( When
i set ReadTimeOut from something else than "0" it rises a EIdReadTimeOut
exception. But could you please show me how to make it work. At least with
pseudo code. My code is like that :
ReadRecord;
if ReadedRecord = recMsg then
TriggerMessageReceive;
if ThereIsAMesageToSend then
SendMessage;
Could you please show me how to make it work on my actual code ? At least as
a pseudo code.
Thank you,
"Remy Lebeau (TeamB)" <XXXX@XXXXX.COM>writes
Quote

"Gollup" <XXXX@XXXXX.COM>writes
news:XXXX@XXXXX.COM...

>My OnExecute code is like this :

That is perfectly fine, as long as your reading is not blocking for so
long
that your writing does not have an oppurtunity to send queued data in a
timely fashion.

However, as has already been mentioned earlier, if you have a thread that
wants to send data to a socket, there is nothing stopping you from simply
writing to that socket directly immediately. Just make sure that you are
providing adequate synchronization to that socket so that multiple packets
being written will not overlap each other.

>When i send a message from the client to server it works fine.
>But when i try to send a message from server to client, it just
>send after the server receives a message from the client.

That is because you are probably reading with infinite timeouts so that
the
reading does not return until data is actually received. To do what you
are
asking, you need to make use of actual timeouts so that the reading stops
reading periodically so that the writing can then proceed when needed.


Gambit
 

Re: Indy demos about the clients

Do i just need to set the ReadTimeOut for clients ?
"Remy Lebeau (TeamB)" <XXXX@XXXXX.COM>writes
Quote
That is because you are probably reading with infinite timeouts so that
the
reading does not return until data is actually received. To do what you
are
asking, you need to make use of actual timeouts so that the reading stops
reading periodically so that the writing can then proceed when needed.
 

Re: Indy demos about the clients

When the server receives a new connection i do :
...(AThread: TIdPeerThread);
begin
AThread.Connection.ReadTimeOut := 10;
end;
It makes EIdReadTimeOut to rise. What else i should do into the OnExecute ?
"Gollup" <XXXX@XXXXX.COM>writes
Quote
Do i just need to set the ReadTimeOut for clients ?

"Remy Lebeau (TeamB)" <XXXX@XXXXX.COM>writes
news:4193e37f$XXXX@XXXXX.COM...

>That is because you are probably reading with infinite timeouts so that
>the
>reading does not return until data is actually received. To do what you
>are
>asking, you need to make use of actual timeouts so that the reading stops
>reading periodically so that the writing can then proceed when needed.


 

Re: Indy demos about the clients

try
ReadRecord;
if ReadedRecord = recMsg then
TriggerMessageReceive;
except
on EIdReadTimeOut do
begin
if ThereIsAMesageToSend then
SendMessage;
end;
end;
Something like that ? At that time i couldn't handle this EIdReadTimeOut
too..
"Remy Lebeau (TeamB)" <XXXX@XXXXX.COM>writes
Quote

"Gollup" <XXXX@XXXXX.COM>writes
news:XXXX@XXXXX.COM...

>My OnExecute code is like this :

That is perfectly fine, as long as your reading is not blocking for so
long
that your writing does not have an oppurtunity to send queued data in a
timely fashion.

However, as has already been mentioned earlier, if you have a thread that
wants to send data to a socket, there is nothing stopping you from simply
writing to that socket directly immediately. Just make sure that you are
providing adequate synchronization to that socket so that multiple packets
being written will not overlap each other.

>When i send a message from the client to server it works fine.
>But when i try to send a message from server to client, it just
>send after the server receives a message from the client.

That is because you are probably reading with infinite timeouts so that
the
reading does not return until data is actually received. To do what you
are
asking, you need to make use of actual timeouts so that the reading stops
reading periodically so that the writing can then proceed when needed.


Gambit


 

Re: Indy demos about the clients

"Gollup" <XXXX@XXXXX.COM>writes
Quote
When i set ReadTimeOut from something else than "0"
it rises a EIdReadTimeOut exception.
As well it should. Simply wrap the code in a try...except block to handle
that situation.
Quote
But could you please show me how to make it work.
At least with pseudo code. My code is like that :
var
bRecordReadOk: Boolean;
begin
try
bRecordReadOk := ReadRecord;
except
On E: Exception do begin
if not (E is EIdReadTimeOut) then raise;
bRecordReadOk := False;
end;
end;
if (bRecordReadOk = True) and (ReadedRecord = recMsg) then begin
TriggerMessageReceive;
end;
if ThereIsAMesageToSend then begin
SendMessage;
end;
end;
Gambit
 

Re: Indy demos about the clients

"Gollup" <XXXX@XXXXX.COM>writes
Quote
Do i just need to set the ReadTimeOut for clients ?
That won't help you on the server side. Timeouts on the client do not
effect the server, and vice versa. Clients have to set their own timeouts
for their own local reading/writing, and servers set their own timeout for
their own local reading/writing.
Gambit
 

Re: Indy demos about the clients

"Gollup" <XXXX@XXXXX.COM>writes
Quote
When the server receives a new connection i do :
<snip>
It makes EIdReadTimeOut to rise.
See my other reply on that matter.
Gambit
 

Re: Indy demos about the clients

"Gollup" <XXXX@XXXXX.COM>writes
Quote
Something like that ?
Almost. You are not checking for outgoing data when an incoming record is
successfully received. If you have a lot of records being received in a
short time, your writing is delayed again. It should be more like this:
try
ReadRecord;
if ReadedRecord = recMsg then
TriggerMessageReceive;
if ThereIsAMesageToSend then
SendMessage;
except
on E: Exception do
begin
if E is EIdReadTimeOut then
begin
if ThereIsAMesageToSend then
SendMessage;
end else
raise;
end;
end;
Which can then become this to remove duplicated code:
begin
try
ReadRecord;
if ReadedRecord = recMsg then
TriggerMessageReceive;
except
on E: Exception do
begin
// do not ignore other Indy exceptions, let them through
if not (E is EIdReadTimeOut) then raise;
end;
end;
if ThereIsAMesageToSend then
SendMessage;
end;
You could then move your try..except into the reading function so that the
OnExecute code is not so clutered:
function ReadRecord(var Record: TRecordType);
begin
Result := False;
try
// read the data here...
Result := True;
except
on E: Exception do
begin
// do not ignore other Indy exceptions, let them through
if not (E is EIdReadTimeOut) then raise;
end;
end;
end;
var
Record: TRecordType;
begin
if ReadRecord(Record) then
begin
if Record = recMsg then
TriggerMessageReceive;
end;
if ThereIsAMesageToSend then
SendMessage;
end;
Gambit
 

Re: Indy demos about the clients

Thanks Remy, i really don't know how to show my happiness :)). That was the
last problem and now it works pretty fine. Thanks a lot.
with my best regards,
Goran,
"Remy Lebeau (TeamB)" <XXXX@XXXXX.COM>writes
Quote

"Gollup" <XXXX@XXXXX.COM>writes
news:XXXX@XXXXX.COM...

>Something like that ?

Almost. You are not checking for outgoing data when an incoming record is
successfully received. If you have a lot of records being received in a
short time, your writing is delayed again. It should be more like this:

try
ReadRecord;

if ReadedRecord = recMsg then
TriggerMessageReceive;

if ThereIsAMesageToSend then
SendMessage;
except
on E: Exception do
begin
if E is EIdReadTimeOut then
begin
if ThereIsAMesageToSend then
SendMessage;
end else
raise;
end;
end;

Which can then become this to remove duplicated code:

begin
try
ReadRecord;
if ReadedRecord = recMsg then
TriggerMessageReceive;
except
on E: Exception do
begin
// do not ignore other Indy exceptions, let them through
if not (E is EIdReadTimeOut) then raise;
end;
end;

if ThereIsAMesageToSend then
SendMessage;
end;

You could then move your try..except into the reading function so that the
OnExecute code is not so clutered:

function ReadRecord(var Record: TRecordType);
begin
Result := False;
try
// read the data here...
Result := True;
except
on E: Exception do
begin
// do not ignore other Indy exceptions, let them through
if not (E is EIdReadTimeOut) then raise;
end;
end;
end;

var
Record: TRecordType;
begin
if ReadRecord(Record) then
begin
if Record = recMsg then
TriggerMessageReceive;
end;
if ThereIsAMesageToSend then
SendMessage;
end;


Gambit