Newsgroups : Borland : borland.public.delphi.internet.winsock : 2007 Mar : Re: Indy10 - TIdTCPConnection, Open/Close, ReadLnTimedOut, Read Thread
| Subject: | Re: Indy10 - TIdTCPConnection, Open/Close, ReadLnTimedOut, Read Thread |
| Posted by: | "Remy Lebeau (TeamB)" (no.spam@no.spam.com) |
| Date: | Tue, 27 Mar 2007 10:47:22 |
"Michael Stieler" <michael.stieler@rie.eu> wrote in message
news:46093f63$1@newsgroups.borland.com...
> This works for 99% of the commands
I doubt that. You are using write buffering with no threshold
specified. Which means that no data will ever be written to the
socket until either WriteBufferFlush() or WriteBufferClose() are
called. If you forget to call it, the data is not sent to the server.
Worse, if something else calls WriteBufferOpen() internally before you
can flush it, then your data is completely lost.
> I get a Timeout in the ReadLn.
Because you are using write buffering, it is likely that not all of
your command data is actually being sent to the server, so the
ReadLn() times out because the server is still waiting for you to
finish sending a full command and thus is not sending back a response
at all.
Get rid of the write buffering. You are not using it correctly
anyway, and it is not gaining you anything useful.
> And I even get it when I set the ReadTimeout up to 2500ms,
> comparing to a TCP Terminal program this can't be the Server's
> fault, there the response is always at once received.
Terminal does not use write buffering, so there is no delay in data
being sent to the server, and thus no delay in its response.
> Is my method of connecting/disconnecting right?
No. You should not be creating a TIdTCPConnection directly in the
first place. You should be using a TIdTCPClient instead, ie:
conn := TIdTCPClient.Create(self);
conn.OnStatus := TcpStatus;
...
if conn.Connected then conn.Disconnect;
Set Host/Port
conn.Connect;
...
conn.IOHandler.Write(String);
...
conn.Disconnect;
conn.IOHandler.InputBuffer.Clear;
> The protocol is very time critical, I assumed this returns faster
> than using no write buffer
You assume wrong. Write buffering is only useful when you perform
multiple writes between the WriteBufferOpen() and
WriteBufferClose/Flush() calls, or sending very large data blocks.
But you are not doing that. You are flushing the buffer after each
Write(). Which effectively circumvents what write buffering is all
about.
> I experimented with Disconnect; and Connect; and so on but
> the Open/Close methods of the Socket seemed to be most
> direct to me.
You are not supposed to be using them directly.
> For the binary data connections I created a TReadThread =
> Class(TThread), that is created when connection is opened, and
> terminated/freed when connection is closed.
That is ok to do.
> Sometimes it occurs, that the thread doesn't terminate.
That is because you are not disconnect the socket properly, so the
thread does not detect it so it can abort any operations that are
pending.
> The thread is as easy as this (without exception handling):
Make sure that your exception handler is allowing the thread to
terminate.
> while (Not Terminated) and conn.Socket.Opened do begin
while (not Terminated) and (conn.Connected) do begin
> I := InputBuffer.Size;
> If I>0 then begin
>
> S := ReadString(I);
Use InputBufferAsString() instead:
S := InputBufferAsString;
if S <> '' then
> One time it happened, the tracer showed me the program was in
> CheckForDataSource() method. Is it possible that this methode
> doesn't return?
Indy uses the socket API select() function to implement its timeouts.
In very very rare occasions, select() has been known to freeze up at
the OS level. Byt it is so rare as to not really even be a problem.
> I read about this method is not thread safe.
It is fine, as long as no other thread is trying to read from the same
socket.
Gambit