Michael Stieler
2007-03-27 15:59:31 UTC
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
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