We are using a Delphi 10.4 application on a Windows 10 PC. This PC is a Client connected to a Server by a SOCKET connection. How can it auto restart the TCP socket after a failure?
A TIdTCPClient
(Indy component) is installed. If the connection failed (when server is switches OFF of a certain time), than communication is not restarting automatically after restarting the Server.
It seems that the Socket connection is blocked or removed after a timeout. Can you explain how this works, and how I can automatically restart the socket?
- Closing and reopening the socket did not help.
- How should I kill the socket?
I tried to close and reopen the socket and to free it. But no effect.
CodePudding user response:
use a try-except block to catch any exceptions that occur when the socket is in use. Then, in the except block, you can close the socket and create a new one to replace it.
for example:
procedure TForm1.Button1Click(Sender: TObject);
var
Socket: TClientSocket;
begin
Socket := TClientSocket.Create(nil);
try
Socket.Host := '127.0.0.1';
Socket.Port := 8080;
Socket.Open;
// use the socket here
except
on E: Exception do
begin
Socket.Free;
Socket := TClientSocket.Create(nil);
// try again
end;
end;
end;
CodePudding user response:
Indy uses sockets that operate in blocking mode exclusively. On the client side, there is no event when a connection to a server is lost. The only way to detect that condition is to perform timely read/write operations on the socket and catch any errors that may be raised. It can take a long time for the OS to timeout a dead connection, so you should configure the client's own ReadTimeout
as needed.
Once you do detect an error, you can simply close and reopen the client.
However, there is a small caveat. When Indy reads bytes from a socket, they are placed in the connection's InputBuffer
until your application code reads them from the connection. After a disconnect occurs, if there are any bytes unread in the InputBuffer
, Indy considers the connection to still be "alive", giving you a chance to finish reading from it until the InputBuffer
is exhausted. So, if you just close and reopen the connection without clearing the InputBuffer
, you may get an "already connected" error, for instance. So, just make sure to Clear()
the InputBuffer
before reopening the connection again.