TIdTCPClient: Reconnect implementation
Asked Answered
P

3

6

I am writing an application, which uses TIdTCPClient to communicated with another application via a socket.

I want the application to try to connect to a certain server until the connection is established (i. e. until the server has gone online).

In order to do this, I wrote following code:

procedure SendingThread.Execute();
var
I : integer;
Test : string;
IsConnected : Boolean;
begin
    TcpClient := TIdTCPClient.Create;
    TcpClient.Host := '127.0.0.1';
    TcpClient.Port := 9999;
    TcpClient.ConnectTimeout := 60000;

    IsConnected := false;
    while not IsConnected do
        begin
        try
            TcpClient.Connect;
            IsConnected := True;
        except
            on E:EIdSocketError do
                IsConnected := false;
        end;
    end;
...
end;

When I run this code with server being offline, I get EIdSocketError with error code 10061. The exception is thrown after TcpClient.Connect;.

How can I modify the code so that this exception in caught in the except cause?

Pantie answered 15/11, 2012 at 13:13 Comment(5)
The TIdTCPClient.Connect is synchronous, so the code you've posted is fine except that you should modify your loop to check also Terminated flag of a thread like while not Terminated and not IsConnected do and except that you can get into infinite connection attempt loop. But you can't get to the line IsConnected := True; after the TcpClient.Connect; is called and the connection fails.Udder
Changing the condition to while (not IsConnected) and (not Terminated) do doesn't fix the error (tried it).Pantie
I know, it's just a suggestion of how you should modify that loop :-) I can't see any error. Have you debugged this code ? I bet 500 of my rep that you'll never reach breakpoint set on the line IsConnected := True; (with the current code) if you'll attempt to connect to a not existing server.Udder
Yes, I'm running the code in the debugger. The question is how to programmatically detect that the server is not available.Pantie
No, the question is at this time How can I modify the code so that the exception in caught in the except clause ? for what would be the answer Don't modify the code, the connection attempt exceptions are already caught.Udder
U
2

There are no code modifications necessary.* Your program is already catching the expected exception.

What you're seeing is the debugger intercepting the exception as soon as it's thrown, before your program gets a chance to see that an exception exists and do anything about it. When the IDE intrerrupts you, it shows a dialog box giving you the option to continue running. Exercise that option, or press the "Run" button after you dismiss the dialog box.

You can configure the debugger to ignore some or all exceptions, which is especially helpful when using Indy, which tends to use exceptions for normal flow control. How to do that has been covered here before.

* Remy's answer describes improvements you can make to your code to catch other possible exceptions.

Upwind answered 15/11, 2012 at 18:8 Comment(0)
N
5

The code you showed is the correct way to handle your reconnect issue, but there is one small change you need to make to it. Change the except block to catch Exception or EIdException instead of EIdSocketError. EIdSocketError is not the only possible exception that Connect() can raise. For instance, it could raise EIdConnectException or EIdConnectTimeout, neither of which are derived from EIdSocketError.

procedure SendingThread.Execute;
var
  ...
  IsConnected : Boolean;
begin
  ...
  IsConnected := False;
  while (not IsConnected) and (not Terminated) do
  begin
    try
      TcpClient.Connect;
      IsConnected := True;
    except
      on E: Exception do
        IsConnected := False;
    end;
  end;
  ...
end;

You can alternatively just remove the on E clause altogether since it is not doing anything useful. The IsConnected variable is already False when the exception is raised, so there is no need to re-assign it to the same value.

procedure SendingThread.Execute;
var
  ...
  IsConnected : Boolean;
begin
  ...
  IsConnected := false;
  while (not IsConnected) and (not Terminated) do
  begin
    try
      TcpClient.Connect;
      IsConnected := True;
    except
    end;
  end;
  ...
end;
Northampton answered 15/11, 2012 at 17:11 Comment(0)
U
2

There are no code modifications necessary.* Your program is already catching the expected exception.

What you're seeing is the debugger intercepting the exception as soon as it's thrown, before your program gets a chance to see that an exception exists and do anything about it. When the IDE intrerrupts you, it shows a dialog box giving you the option to continue running. Exercise that option, or press the "Run" button after you dismiss the dialog box.

You can configure the debugger to ignore some or all exceptions, which is especially helpful when using Indy, which tends to use exceptions for normal flow control. How to do that has been covered here before.

* Remy's answer describes improvements you can make to your code to catch other possible exceptions.

Upwind answered 15/11, 2012 at 18:8 Comment(0)
L
-1

While loop is not necessary here since you are already in a thread execute and this while loop will be executed only once always and if not connected your thread will be in in an indefinite loop.

Loria answered 18/6, 2014 at 22:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.