OpenNetworkConnection() - How to determine timeout

Linux specific forum
Marlin
Enthusiast
Enthusiast
Posts: 406
Joined: Sun Sep 17, 2006 1:24 pm
Location: Germany

OpenNetworkConnection() - How to determine timeout

Post by Marlin »

Hi,

I just tried

Code: Select all

Connection = OpenNetworkConnection(\Host, 80, #PB_Network_TCP)
to a server that is apparently down at the moment.

This takes quite a while, maybe 3 to 5 minutes until it finally returns
and Connection = 0.

Is there a way to shorten that timeout?
(I would like to set it to 20 - 30 seconds.)
Thalius
Enthusiast
Enthusiast
Posts: 711
Joined: Thu Jul 17, 2003 4:15 pm
Contact:

Re: OpenNetworkConnection() - How to determine timeout

Post by Thalius »

This might point you in the right direction:
SO_RCVTIMEO and SO_SNDTIMEO

from: http://linux.die.net/man/7/socket

Cheers,
Thalius
"In 3D there is never enough Time to do Things right,
but there's always enough Time to make them *look* right."
"psssst! i steal signatures... don't tell anyone! ;)"
Marlin
Enthusiast
Enthusiast
Posts: 406
Joined: Sun Sep 17, 2006 1:24 pm
Location: Germany

Re: OpenNetworkConnection() - How to determine timeout

Post by Marlin »

Thalius wrote:This might point you in the right direction:
SO_RCVTIMEO and SO_SNDTIMEO

from: http://linux.die.net/man/7/socket
Thanks for the hint Thalius.

This appears to be more complicated than I thought.

I haven't gotten to trying something with SO_RCVTIMEO and SO_SNDTIMEO yet.
(I would need to find out how I can use those from within PB.)

Also they do not seem to be quite what I would need,
as they seem to apply to receiving and sending network data.

For those cases I can determine my own timeouts by polling NetworkClientEvent/NetworkServerEvent...
(SendNetworkData() fortunately does not appear to block...)

Looking at http://linux.die.net/man/2/connect, I find:
ETIMEDOUT
Timeout while attempting connection. The server may be too busy to accept new connections.
Note that for IP sockets the timeout may be very long when syncookies are enabled on the server.
however with not suggestion, if or how this can be shortened.

Now I see a possible solution:
I could call OpenNetworkConnection() inside a thread...
In case the thread gets the connection opened after my
Timeout has elapsed, it is required to close it again.
Thalius
Enthusiast
Enthusiast
Posts: 711
Joined: Thu Jul 17, 2003 4:15 pm
Contact:

Re: OpenNetworkConnection() - How to determine timeout

Post by Thalius »

Syn Cookies should be enabled - to prevent SYN flooding or connections will drop in that case.

you can enable / disable them using Magick flags:

Code: Select all

# enable
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
# disable
echo 0 > /proc/sys/net/ipv4/tcp_syncookies
as i see oyu want to connect to a HTTP Port - you might want to give this a try:
http://www.purebasic.fr/english/viewtop ... 12&t=29388

originally pretty old source - but if this timeout method works for you ( here it does ) then thats leaner than using a thread. Rather id recommend using then the Socket::Bind / connect API ( same as under windows called via _ iirc. ).

id post a example but am at work atm - no linux i can fondle on and as always in this job - too much work to even light a cig... :roll:


Cheers,
Thalius
"In 3D there is never enough Time to do Things right,
but there's always enough Time to make them *look* right."
"psssst! i steal signatures... don't tell anyone! ;)"
walker
Enthusiast
Enthusiast
Posts: 634
Joined: Wed May 05, 2004 4:04 pm
Location: Germany

Re: OpenNetworkConnection() - How to determine timeout

Post by walker »

here is an (imho) easy way to use PB commands only:

Code: Select all


Global Mutex = CreateMutex()

Procedure http_connect(param)
    LockMutex(Mutex)
    Debug "Trying to connect ....."
    If  OpenNetworkConnection("google.de", 80)
        Debug "Connection established!"
    EndIf
    UnlockMutex(mutex)
EndProcedure

Debug "Starting..."
If InitNetwork()
    Debug "Init Network ok"
    ;threaded open network
    Debug "starting thread ..."
    mt = CreateThread(@http_connect(), 0)    
    If WaitThread(mt, 5000) = 0
        Debug "Connection failed"
    EndIf
Else
    Debug "no Network available"
EndIf
mayby not well optimized :roll: but working (at least on Linux x64 - but should work on all OS)
Try a non reachable IP such as 192.168.111.1 (if not your ip at home ;-)) to see the difference
the timeout is conrtolled by the paramater at CreateThread....
Marlin
Enthusiast
Enthusiast
Posts: 406
Joined: Sun Sep 17, 2006 1:24 pm
Location: Germany

Re: OpenNetworkConnection() - How to determine timeout

Post by Marlin »

Thalius wrote:

Code: Select all

# enable
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
# disable
echo 0 > /proc/sys/net/ipv4/tcp_syncookies
I do not seem to have a file
"/proc/sys/net/ipv4/tcp_syncookies"
on my machine.

(I could probably find an option for syncookies somewhere in the kernel configuration
and recompile my kernel with the changed settings, but I do not really like that idea
so much.)

Also, as far as I understood it, it should be an option for the server (not for the client).
Thalius wrote:as i see oyu want to connect to a HTTP Port - you might want to give this a try:
viewtopic.php?f=12&t=29388

originally pretty old source - but if this timeout method works for you ( here it does ) then thats leaner than using a thread
Thank you Thalius, I do have some coded infrastructure with similar functions allready.
(Except my focus is not on downloading files in this case.)

You catch the situation when the connect fails and treat it as a timeout:

Code: Select all

...
  *this\ConID = OpenNetworkConnection( *this\Host , #HTTP_Port )

  If *this\ConID
...
  Else
    ;// Connection Timeout
    PureHTTP_SET_STATUS(*this,#PureHTTP_STATUS_TIMEOUT)
  EndIf
Depending on the usage, that could be true with some probability.

But you would still need to wait until OpenNetworkConnection() returns.
I did not see anything in your code that would shorten that timeout.

@walker: exactly, this is the approach, I have in mind.
This principle will work independent of platform (probably).

When I get to it again, I will probably do it that way,
also making shure, connections opened by the thread,
after my timeout are closed asap...
(As mentioned above)
Marlin
Enthusiast
Enthusiast
Posts: 406
Joined: Sun Sep 17, 2006 1:24 pm
Location: Germany

Re: OpenNetworkConnection() - How to determine timeout

Post by Marlin »

This is the solution that seems to work for me:

Code: Select all

Global MutexCheckTimeout.i = CreateMutex()

; Open Network Connection with Timeout:
Structure NetCon_struct
  ServerName.s
  Port.l
  Mode.l
  Thread.i
  Connection.l
  NotTimedOut.b
  CallerCleanUp.b
EndStructure

; Thread procedure:
Procedure OpenNetConThread(*pNetCon.NetCon_struct)
  With *pNetCon
    \Connection = OpenNetworkConnection(\ServerName, \Port, \Mode)
    LockMutex(MutexCheckTimeout)
    If \NotTimedOut
      \CallerCleanUp = #True
      UnlockMutex(MutexCheckTimeout)
      ProcedureReturn
    Else
      If \Connection
        CloseNetworkConnection(\Connection)
      EndIf
      FreeMemory(*pNetCon)
      UnlockMutex(MutexCheckTimeout)
      ProcedureReturn
    EndIf
  EndWith
EndProcedure

; Like OpenNetworkConnection, but with timeout:
Procedure.l OpenNetConnection (pServerName.s, pPort.l, pMode.l, pTimeout.l)
  Protected *NetCon.NetCon_struct
  Protected Connection.l
  
  *NetCon = AllocateMemory(SizeOf(NetCon_struct))
  With *NetCon
    \ServerName = pServerName
    \Port = pPort
    \Mode = pMode
    \NotTimedOut = #True
    \Thread = CreateThread(@OpenNetConThread(), *NetCon)
    \NotTimedOut = WaitThread(\Thread, pTimeout)
    If \NotTimedOut
      Connection = \Connection
      FreeMemory(*NetCon)
      ProcedureReturn Connection
    Else
      LockMutex(MutexCheckTimeout)
      If \CallerCleanup  ; Thread did not find out about timeout but was almost done
        Connection = \Connection
        FreeMemory(*NetCon)
        UnlockMutex(MutexCheckTimeout)
        ProcedureReturn Connection
      Else  ; Thread will close connection (if connected) and clean up memory
        UnlockMutex(MutexCheckTimeout)
        ; even if there was a connection by this time,
        ; we can not use it, as the thread would close it immediately ...
        ProcedureReturn 0
      EndIf
    EndIf
  EndWith
EndProcedure
Post Reply