Forum > Networking and Web Programming

[SOLVED]fpconnect (from sockets unit) takes a long time to say the server is off

(1/1)

arturogr:
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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program socket_client;...uses  {$IFDEF UNIX}  cthreads,  {$ENDIF}  Classes, Sockets, SysUtils;  ...// here, the program halts for about 25 seconds before issuing the connection error if "server" is not running.  if fpconnect(SockDesc, @SockAddr, SizeOf(SockAddr)) = -1 then    PError('[Client] Connect : ');                              ... 
Thanks for your help and ideas.

Leledumbo:
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:

--- Quote from: Leledumbo on December 05, 2023, 06:53:59 am ---fpConnect relies on the underlying OS' socket implementation, which unfortunately for connect, has no timeout control at least on Windows and Linux.

--- End quote ---
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.

MarkMLl:

--- Quote from: TRon on December 05, 2023, 07:27:00 am ---
--- Quote from: Leledumbo on December 05, 2023, 06:53:59 am ---fpConnect relies on the underlying OS' socket implementation, which unfortunately for connect, has no timeout control at least on Windows and Linux.

--- End quote ---
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.

--- End quote ---

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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---                  if IsBlocking in blocking then begin                    timeout.tv_sec := 0; (* Treat this as a blocking call       *)                    timeout.tv_usec := 0                  end else begin                    timeout.tv_sec := 0; (* Treat this as a non-blocking call   *)                    timeout.tv_usec := 10000 (* with this timeout in uSec.      *)                  end;                  if fpSetSockOpt(fSocket, SOL_SOCKET, SO_RCVTIMEO, @timeout, SizeOf(timeout)) < 0 then begin            {$if declared(StrError) }                    WriteLn(stderr, 'SetSockopt error ' + IntToStr(SocketError) + ': ' + StrError(SocketError))            {$endif declared        }                  end;                  sockLen := SizeOf(sockAddr);                  fClient := fpAccept(fSocket, @sockAddr, @sockLen); (* See timeout above *)                  if (fClient < 0) and not (IsBlocking in blocking) then                    exit(false);        (* No incoming connection, return no character *) 
MarkMLl

arturogr:
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.

Navigation

[0] Message Index

Go to full version