Indy10 - TIdTCPConnection, Open/Close, ReadLnTimedOut, Read Thread

Giganews Newsgroups
Subject: Indy10 - TIdTCPConnection, Open/Close, ReadLnTimedOut, Read Thread
Posted by:  Michael Stieler (michael.stiel…@rie.eu)
Date: Tue, 27 Mar 2007

Hello,

  a write an application that has to handle multiple TCP Connections.
Two of them have sort of a telnet protocol, the others are binary.
For each connection I create an "Object" inherited from TComponent, in
which the connection is initialized as follows:

conn := TIdTcpConnection.Create(self);
conn.CreateIOHandler;
conn.Socket.WriteBufferOpen;
conn.Socket.OnStatus := TcpStatus;

The telnet sort connection is a Command+Response system. Because of
problems I had with the IdTelnetClient, I also use the IdTcpConnection
class here (Linefeed is LF+CR for one response, the others CR+LF)

Executing a command works like that:
conn.Socket.Write(strCommand+CR+LF);
A := conn.Socket.ReadLn(CR+LF);

1. Question
-----------
This works for 99% of the commands, and then I get a Timeout in the
ReadLn. 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. It seems to get worse
when talking to two Servers, although I call ReadLn sequentially. I put
the periodically execution of the commands in a TThread so the main
application doesn't freeze, but what could it be that I get those
ReadLnTimeOuts so often?

2. Question
-----------
Is my method of connecting/disconnecting right?

Connecting
If (conn.Socket.Opened) then conn.Socket.Close;
Setting Host/Port
conn.Socket.Open;

Writing
conn.Socket.Write(String);
conn.Socket.WriteBufferFlush;
(The protocol is very time critical, I assumed this returns faster than
using no write buffer)

Disconnecting
conn.Socket.Close;
conn.Socket.InputBuffer.Clear;
(Data left in InputBuffer could make the connection look like open)

I experimented with Disconnect; and Connect; and so on but the
Open/Close methods of the Socket seemed to be most direct to me.

3. Question
-----------
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.

Sometimes it occurs, that the thread doesn't terminate. I close the
connection as follows:

conn.Socket.Close;
conn.Socket.InputBuffer.Clear;
  if readThread <> nil then begin
    // Between here..
      readThread.Terminate;
      readThread.WaitFor;
      FreeAndNil(readThread);
    // and here the program freezes in CsrNewThread of a System DLL
  end;

The thread is as easy as this (without exception handling):

while (Not Terminated) and conn.Socket.Opened do begin

        With conn.Socket do begin

            CheckForDataOnSource(1000);
            If not Opened then break;

            I := InputBuffer.Size;
            If I>0 then begin

              S := ReadString(I);
              If Assigned( FOnRead ) then
                FonRead(conn, S);  // Not Synchronized read event

            end;
        end;
End;

One time it happened, the tracer showed me the program was in
CheckForDataSource() method. Is it possible that this methode doesn't
return? I read about this method is not thread safe. I don't access
buffer or read functions during the run-time of this thread.

Indy-Version is the Dev-Snapshot from Fulgan.com

Thanks for your help..

  Michael Stieler

Replies