Recent

Author Topic: [SOLVED]fpconnect (from sockets unit) takes a long time to say the server is off  (Read 1333 times)

arturogr

  • Newbie
  • Posts: 5
I have the client and the server programs; but when the server side is not running, the "fpconnect" from the sockets unit (the client program) takes about 25 seconds to recognize the server is off-line (error).

¿is there a way to handle the max time that "fpconnect" call should wait for a server response?

Client:
Code: Pascal  [Select][+][-]
  1. program socket_client;
  2. .
  3. .
  4. .
  5. uses
  6.   {$IFDEF UNIX}
  7.   cthreads,
  8.   {$ENDIF}
  9.   Classes, Sockets, SysUtils;  
  10. .
  11. .
  12. .
  13. // here, the program halts for about 25 seconds before issuing the connection error if "server" is not running.
  14.   if fpconnect(SockDesc, @SockAddr, SizeOf(SockAddr)) = -1 then
  15.     PError('[Client] Connect : ');                              
  16. .
  17. .
  18. .
  19.  

Thanks for your help and ideas.
« Last Edit: December 09, 2023, 09:39:47 am by arturogr »

Leledumbo

  • Hero Member
  • *****
  • Posts: 8774
  • Programming + Glam Metal + Tae Kwon Do = Me
fpConnect relies on the underlying OS' socket implementation, which unfortunately for connect, has no timeout control at least on Windows and Linux. You can either go low with the platform specific socket implementation or go higher with fcl-net's ssockets. At least TInetSocket has connect timeout feature implemented.

TRon

  • Hero Member
  • *****
  • Posts: 3623
fpConnect relies on the underlying OS' socket implementation, which unfortunately for connect, has no timeout control at least on Windows and Linux.
You can set the overal tcp timeout but I would advise against it as it is a global option.

In order to control the timeout for a connect you need to use a socket in non blocking mode (it is using blocking mode by default). You can set the socket in non blocking mode with ioctl and use select to check for the timeout.
« Last Edit: December 05, 2023, 07:29:21 am by TRon »
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

MarkMLl

  • Hero Member
  • *****
  • Posts: 8015
fpConnect relies on the underlying OS' socket implementation, which unfortunately for connect, has no timeout control at least on Windows and Linux.
You can set the overal tcp timeout but I would advise against it as it is a global option.

In order to control the timeout for a connect you need to use a socket in non blocking mode (it is using blocking mode by default). You can set the socket in non blocking mode with ioctl and use select to check for the timeout.

In my experience there is no universally-correct answer to this, since the local computer doesn't cache the "up" state of its neighbours- at least as far as pure IP-based protocols are concerned. If the target machine is up it might respond to a request immediately, or there again it might not if there's a tarpit or a port-knocking filter installed.

You could start off by pinging the target, but depending on your local OS you might find you need elevated privilege to do that under program control. But again, many systems disable their ICMP Echo (i.e. "Ping") response.

You can modify most of the Berkeley Sockets API using setsockopt() or, in extremis, select(). I can't find a recent example in my code of doing that to fpListen(), but by analogy and possibly as a useful starting point for experimentation:

Code: Pascal  [Select][+][-]
  1.                   if IsBlocking in blocking then begin
  2.                     timeout.tv_sec := 0; (* Treat this as a blocking call       *)
  3.                     timeout.tv_usec := 0
  4.                   end else begin
  5.                     timeout.tv_sec := 0; (* Treat this as a non-blocking call   *)
  6.                     timeout.tv_usec := 10000 (* with this timeout in uSec.      *)
  7.                   end;
  8.                   if fpSetSockOpt(fSocket, SOL_SOCKET, SO_RCVTIMEO, @timeout, SizeOf(timeout)) < 0 then begin
  9.             {$if declared(StrError) }
  10.                     WriteLn(stderr, 'SetSockopt error ' + IntToStr(SocketError) + ': ' + StrError(SocketError))
  11.             {$endif declared        }
  12.                   end;
  13.                   sockLen := SizeOf(sockAddr);
  14.                   fClient := fpAccept(fSocket, @sockAddr, @sockLen); (* See timeout above *)
  15.                   if (fClient < 0) and not (IsBlocking in blocking) then
  16.                     exit(false);        (* No incoming connection, return no character *)
  17.  

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

arturogr

  • Newbie
  • Posts: 5
I read a few pages to understand the basic in TCP (chapter 7 of "TCP/IP SOCKETS IN C") to have a better idea of sockets power. Good chapter.

http://debracollege.dspaces.org/bitstream/123456789/406/1/TCPIP%20Sockets%20in%20C%20by%20Michael%20J.%20Donahoo.pdf

and the options for "setsockopt" function:

https://www.ibm.com/docs/en/zos/2.3.0?topic=functions-setsockopt-set-options-associated-socket

and other ideas:

https://man.archlinux.org/man/unix.7.en

And finally, I got the answer: There is not that option for sockets. There is no such whim.  :'(

It is not possible to handle the max time to wait for a "fpconnect()" call at the client side when the server is not reachable. We have to wait for the error for that connection attempt.

Thanks all of you, for your time and patience.
« Last Edit: December 09, 2023, 09:36:48 am by arturogr »

 

TinyPortal © 2005-2018