Recent

Author Topic: TIdTCPClient.connect how to check if server is running  (Read 732 times)

Dzandaa

  • Full Member
  • ***
  • Posts: 248
  • From C# to Lazarus
TIdTCPClient.connect how to check if server is running
« on: June 14, 2022, 11:57:19 am »
Hi everybody,

Working with Lazarus Pascal 2.012 FPC 2.3.0 on Windows, Linux and MacOS

I'm using Indy10 to connect to a custom made ESP32 based WiFi camera.

using
Client: TIdTCPClient;


Everything is working fine, but I have to use a TIdIcmpClient  to check that the camera server is online before using Client.Connect or
it crashes.

The problem in Linux is that TIdICMPClient requires root access and I don't want that :).

Any other Idea?

Thank you.




Dzandaa

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1312
    • Lebeau Software
Re: TIdTCPClient.connect how to check if server is running
« Reply #1 on: June 14, 2022, 06:33:22 pm »
I'm using Indy10 to connect to a custom made ESP32 based WiFi camera.
...
Everything is working fine, but I have to use a TIdIcmpClient  to check that the camera server is online before using Client.Connect or it crashes.

Crashes how, exactly?  TIdTCPClient.Connect() raises an exception if it can't connect to the server. That is not a crash, unless your code is not handling the exception properly.

ICMP will tell you only whether the device is reachable on the network.  It will not tell you if the device has a running TCP server that can be connected to.  You still have to call TIdTCPClient.Connect() regardless.  So, your best option is to simply wrap the TIdTCPClient.Connect() call in a try..except block to catch the exception, and then move on with your code logic as needed.

The problem in Linux is that TIdICMPClient requires root access and I don't want that :).

Known issue: https://github.com/IndySockets/Indy/issues/122

The workaround is to use ICMP over a SOCK_DGRAM socket, which does not require root access, rather than a SOCK_RAW socket:

Unprivileged ICMP sockets on Linux.

ICMP sockets (linux)

Indy doesn't have any high-level components that allow you to create such a socket (all uses of SOCK_DGRAM are limited to IPPROTO_UDP), but you can probably cobble something together using Indy's TIdSocketHandle and/or TIdStack... classes directly.

Also, there are caveats with this DGRAM+ICMP approach, ie:

- only ICMP echo requests are supported
- may not be implemented uniformly across different Linux distributions
- ports are used as message identifiers
- may require a call to sysctl to enable: https://lkml.org/lkml/2011/5/18/305
« Last Edit: June 14, 2022, 06:35:01 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

Dzandaa

  • Full Member
  • ***
  • Posts: 248
  • From C# to Lazarus
Re: TIdTCPClient.connect how to check if server is running
« Reply #2 on: June 14, 2022, 07:29:42 pm »
Hi again,

Here is part of my code running in a thread

Code: Pascal  [Select][+][-]
  1. // **************************************
  2. // ***** Initiate Camera Connection *****
  3. // **************************************
  4. function TCamThread.CamConnect(): boolean;
  5. begin
  6.  try
  7.   TaskClient.Connect;
  8.  except
  9.   on E: Exception do
  10.   begin
  11.    ShowMessage('Cannot connect: ' + E.Message);
  12.    exit(false);
  13.   end;
  14.  end;    
  15.  
  16. ...
  17.  exit(True);
  18. end;
  19.  

I tested in debug mode and it never reach ShowMessage

And the crash:

Quote
Project ESP32Cam raised exception class 'EIDNotASocket' with message:
Socket Error # 1003Socket operation on non-socket

In file 'System\IdStack.pas' at line 942

I don't have enough documentation and examples on Indy10 and the manual is not available (http://ww2.indyproject.org : server not found)

an example would be welcome :)


Dzandaa

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1312
    • Lebeau Software
Re: TIdTCPClient.connect how to check if server is running
« Reply #3 on: June 14, 2022, 08:28:15 pm »
Here is part of my code running in a thread

ShowMessage() is not thread-safe. And where is TaskClient defined and initialized before CamConnect() is called? Can you provide an example that actually compiles?

I tested in debug mode and it never reach ShowMessage

And the crash:

Quote
Project ESP32Cam raised exception class 'EIDNotASocket' with message:
Socket Error # 1003Socket operation on non-socket

Again, that is not a crash.  That is just a normal exception.  And your code is clearly running inside the debugger, which is catching the exception first.  Are you instructing the debugger to continue execution so the exception is passed back to your application for handling?

In file 'System\IdStack.pas' at line 942

That is the line of code that is actually raising the exception, in response to a socket function returning an ENOTSOCK error code:

Code: Pascal  [Select][+][-]
  1. procedure TIdStack.RaiseSocketError(AErr: integer);
  2. begin
  3.   ...
  4.   if AErr = Id_WSAENOTSOCK then begin
  5.     ...
  6.     raise EIdNotASocket.CreateError(AErr, WSTranslateSocketErrorMsg(AErr)); // <-- line 942
  7.   end;
  8.   ...
  9. end;

But, what does the call stack look like that is leading up to that error?  It is very unusual for TIdTCPClient.Connect() to encounter that particular error, unless you are misusing the TIdTCPClient object, which we can't see since you did not provide enough code yet.

the manual is not available (http://ww2.indyproject.org : server not found)

https://www.indyproject.org/2021/02/10/links-to-old-indy-website-pages-are-currently-broken/
« Last Edit: June 14, 2022, 08:30:15 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

Dzandaa

  • Full Member
  • ***
  • Posts: 248
  • From C# to Lazarus
Re: TIdTCPClient.connect how to check if server is running
« Reply #4 on: June 15, 2022, 11:26:22 am »
Hello,

Thank you Remy,

My program works now, in fact everything was OK (except ShowMessages which was just a test)
Effectively, I stopped the program when the debugger showed me the error ;)
I didn't know the debugger showed the error before jumping into except.

when I pass the error, the exception works fine. And in the release version, no problem.
Thank you very much.
Dzandaa

 

TinyPortal © 2005-2018