Sign in to follow this  
Followers 0
matrix200

TCPConnect timeout

39 posts in this topic

The question is does the tcptimeout option actually change the time it takes for tcpconnect to give up?

I am asking that because I tried to play with the value of that option and it always seems

to take about the same time until the tcpconnect fails no matter what tcptimeout value I set.

Naturally my whole program becomes unresponsive until the timeout occurs.

This is very annoying for the users of my program and the truth is I am puzzled as to how

make the tcptimeout value to be used except for actually doing all the tcp stuff with dll calls which I obviously don't want to do.

Share this post


Link to post
Share on other sites



I think TCPTimeout has to do with if the connection has been dropped, not as a give-up time for connecting.

Share this post


Link to post
Share on other sites

So what you say is that initial connect timeout is hard coded and the only way to use a different one is to write tcpconnect of my own?

Share this post


Link to post
Share on other sites

I don't think it will help Helge

The tcpconnect is blocking so no matter what kind of timer I put outside I still will wait

the same time for the function to fail.

Looks like there is no way to have tcpconnect with timeout.

I think it could be nice feature request for the next version , what do you guys think?

Share this post


Link to post
Share on other sites

Oh, I see what you meant now. I thought you wanted some kind of a reattempt-until-timeout thingie.

Share this post


Link to post
Share on other sites

So anyone has any idea how to get a real timeout on tcpconnect?

It looks somewhat problematic to use windows winsock api because wsstartup requires some complex struct one of fields for which is a pointer to string.

I tried calling that but the script crashes (with an application error).

I also checked oswinsck.dll which is a com interface but I don't have timeout there either.

Any ideas how to re-implement tcp using dll calls?

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Hey Larry thanks for reply.

I also digged the matters a little deeper and I am afraid it is kinda impossible.

That timeout is actually part of certain variables in tcp protocol implementation and I think it is pretty much impossible to change them.

The timeout consists of some small timeout value which is multiplied by a number of retries before giving up.

Both values are defines or constants in the tcp implementation.

I saw a similar request for somebody using BSD and the answer was to change their values in the code and recompile.

That is not possible in windows I guess :)

The only other way they propose is to use the non blocking version somehow.

I am not sure it is possible in AUTOIT either since it is one threaded.

[EDIT]

I did some more research and apparently the best way to implement that is by by using non blocking sockets.

Then after you invoke winsock connect it immidiately returns with status connecting.

You can then poll it and decide yourself when you don't want to wait anymore and call it quits.

Edited by matrix200

Share this post


Link to post
Share on other sites

Ok I think I have a solution using oswinsock com object.

Here is an example code for tcp connect with timeout

CODE

#include <Process.au3>

CONST $SCKTCPPROTOCOL = 0

CONST $SCKUDPPROTOCOL = 1

Const $SCKCLOSED = 0

Const $SCKOPEN = 1

Const $SCKLISTENING = 2

Const $SCKCONNECTIONPENDING = 3

Const $SCKRESOLVINGHOST = 4

Const $SCKHOSTRESOLVED = 5

Const $SCKCONNECTING = 6

Const $SCKCONNECTED = 7

Const $SCKCLOSING = 8

Const $SCKERROR = 9

Func InitTCP()

$runstring = "regsvr32 /s " & @scriptDir & "\OSWINSCK.dll"

$status = _RunDos($runstring)

return $status

EndFunc

Func Connect($addr , $port , $timeout )

$socket = ObjCreate("OSWINSCK.Winsock")

if $socket == 0 Then ;failed to initialize the com object

return -1; maybe oswinsock not registered?

EndIf

$socket.Protocol = $SCKTCPPROTOCOL ; set protocol to be tcp

$timer = TimerInit()

$socket.Connect($addr , $port )

while True

if $socket.State == $SCKERROR Then

return -2 ;connection error (will give up for now)

EndIf

if $socket.State == $SCKCONNECTED Then

ConsoleWrite("timeout " & TimerDiff($timer) & @CRLF)

return $socket ; return object for connection

EndIf

if TimerDiff($timer) > $timeout Then

ConsoleWrite("timeout " & TimerDiff($timer) & @CRLF)

return -3 ; connection timeout

EndIf

Sleep(50)

WEnd

EndFunc

InitTCP()

Connect("192.168.0.34",3493 ,500)

In this code You define timeout up to 50ms.

Meaning you may exceed your timeout max 50 ms.

This of course can be changed by using Sleep with smaller value.

The other problem with that code is that tcp timeout will still kick you out.

It can be solved by either retrying connect on socketerror (after determining that the error is indeed tcp timeout) or wrapping this connect function in another one which will take care of that in a way Helge proposed earlier in the thread.

The other problem I am concerned about is gui responsivness when calling that function.

Clearly if you give a big timeout value your gui still will be non responsive during function call.

How that could be solved?

Share this post


Link to post
Share on other sites

I am having the same problems with TCPConnect() to, for example, "pop.yourserver.com"

It takes 25 seconds thats rgith 25 seconds to timeout.

The problem with the control you mention and the MSWINSCK.OCX control I am looking at (that i dont knoe how to use with AutoIt) and need both licencing i.e. money to use for commercial prurposes and require installation (DLL registration) ont he users PC before use.

I am thinking about a dummy GUI control but I dont know if that will work either a second spawned app would be doable but alot of unneeded work and not to mention the socket hanlde will probably be unavailable to the calling process...

Any real help would be appreciated: all we need is an asynchonous TCPConnect() call that sets a global flag/semaphore or a single extra thread functionality in AutoIt and onyl TCPConnect() needs to be reentrant in AutoIt as the routine can simply set a flag as suggested.

If someone would like to give me access to the code I am volunteer to fix it....

My alternative is to move my AutoIt pop email checker prototype to Python.

This socket implementation in AutoIt renders is a WIN3.1 architectire laguage im afraid I have fixed all my other TCP timeout issues by doing the euivalent of a Sleep($tcptimeout) rather than Opt("TCPTimeout", $tcptimeout)

Regards.

Share this post


Link to post
Share on other sites

I am having the same problems with TCPConnect() to, for example, "pop.yourserver.com"

It takes 25 seconds thats rgith 25 seconds to timeout.

The problem with the control you mention and the MSWINSCK.OCX control I am looking at (that i dont knoe how to use with AutoIt) and need both licencing i.e. money to use for commercial prurposes and require installation (DLL registration) ont he users PC before use.

I am thinking about a dummy GUI control but I dont know if that will work either a second spawned app would be doable but alot of unneeded work and not to mention the socket hanlde will probably be unavailable to the calling process...

Any real help would be appreciated: all we need is an asynchonous TCPConnect() call that sets a global flag/semaphore or a single extra thread functionality in AutoIt and onyl TCPConnect() needs to be reentrant in AutoIt as the routine can simply set a flag as suggested.

If someone would like to give me access to the code I am volunteer to fix it....

My alternative is to move my AutoIt pop email checker prototype to Python.

This socket implementation in AutoIt renders is a WIN3.1 architectire laguage im afraid I have fixed all my other TCP timeout issues by doing the euivalent of a Sleep($tcptimeout) rather than Opt("TCPTimeout", $tcptimeout)

Regards.

I would be very interested in having a TCPconnect timeout function added as part of the standard networking suite in AutoIt as well. Very hard to scan thousands of ports on thousands of computers as an enterprise admin when you have to wait for 20 seconds for the connection attempt to timeout for each port scanned.

I have tried the code above that references the winsock dll's and it works just fine for me. I actually built a full blown port scanner in VB using the Winsock library at one point, and was hoping not to have to go back to that legacy VB6 code just to write a simple port scanning script in Autoit.

All in all, I have to agree that calling mswinsck is a half solution - this would be a great addition to Autoit to have this ability added natively.

By the way, if Opt("TCPTimeout", 100) doesn't set the connection timeout parameters, does anyone know exactly what it does?

Thanks - John

Share this post


Link to post
Share on other sites

in *.vbs this code work

'http://www.ostrosoft.com/oswinsck.asp

Dim oWinsock
Dim sBuffer
Dim sSource
Dim bClose
Dim stdOut
Set stdOut = WScript.StdOut

sBuffer = "": sSource = "": bClose = False


Set oWinsock = CreateObject("OSWINSCK.Winsock")
WScript.ConnectObject oWinsock, "oWinsock_"

oWinsock.Connect "129.6.15.28", 13

Sub oWinsock_OnClose()
  WScript.Echo sSource
  'stdOut.Write(sSourse)
  oWinsock.CloseWinsock
  bClose = True
  Set oWinsock = Nothing
End Sub

Sub oWinsock_OnDataArrival(byVal Total)
  oWinsock.GetData sBuffer
  sSource = sSource & sBuffer
End Sub

While Not bClose
  WScript.Sleep 1
Wend

but i don't know convert this code to autoit

Share this post


Link to post
Share on other sites

this would be a great addition to Autoit to have this ability added natively.

I greatly agree with Jsunn!

tolle indicium

Share this post


Link to post
Share on other sites

Make sure first to have the type library installed. Keep in mind that reducing the timeout value give fast results but false ones:

#include <Array.au3>
Opt('MustDeclareVars', 1)

Global Const $SCKTCPPROTOCOL = 0
Global Const $SCKUDPPROTOCOL = 0x01
Global Const $SCKCLOSED = 0
Global Const $SCKOPEN = 0x01
Global Const $SCKLISTENING = 0x02
Global Const $SCKCONNECTIONPENDING = 0x03
Global Const $SCKRESOLVINGHOST = 0x04
Global Const $SCKHOSTRESOLVED = 0x05
Global Const $SCKCONNECTING = 0x06
Global Const $SCKCONNECTED = 0x07
Global Const $SCKCLOSING = 0x08
Global Const $SCKERROR = 0x09

Dim $sIPADDRESS = '68.180.206.184'  ; http://www.yahoo.com - at the moment

Dim $result = _ScanPorts($sIPADDRESS, 260, 80, 100)

If Not IsArray($result) Then
    Switch $result
        Case -2
            MsgBox(0x10, "Host not reachable", "The host could not be reached")

        Case -3
            MsgBox(0x30, "Timeout not defined", "Please insert the desired amount of timeout(ms)")
    EndSwitch
Else
    _ArrayDisplay($result, 'Finish scanning IP address: ' & $sIPADDRESS)
EndIf

Exit



Func _ScanPorts($sIPADDRESS, $iTimeout, $iFrom, $iTo)
    Local $i, $step, $index = 0
    Local $ping, $result, $aResults[1]

    $ping = Ping($sIPADDRESS, $iTimeout)

    If Not $ping Then Return -2

    If $iTo < $iFrom Then
        $step = -1
        ReDim $aResults[$iFrom-$iTo+1]
    Else
        $step = 1
        ReDim $aResults[$iTo-$iFrom+1]
    EndIf


    For $i = $iFrom To $iTo Step $step
        $result = Connect($sIPADDRESS, $i, $iTimeout)
        If Not $result Then
            $aResults[$index] = 'Port: ' & $i & ' is open'
            $index += 1
        Else
            $aResults[$index] = 'Port: ' & $i & ' is not open'
            $index += 1
        EndIf
    Next

    Return $aResults
EndFunc   ;==>_ScanPorts


Func Connect($sAddr, $iPort, $iTimeout)

    Local $oSocket, $timer
    $oSocket = ObjCreate("OSWINSCK.Winsock")

    $oSocket.Protocol = $SCKTCPPROTOCOL ; set protocol to be tcp
    $timer = TimerInit()
    $oSocket.Connect($sAddr, $iPort)

    While 1

        If $oSocket.State = $SCKERROR Then
            $oSocket = 0
            Return -2 ;connection error (will give up for now)
        EndIf

        If $oSocket.State = $SCKCONNECTED Then
            ;ConsoleWrite("timeout " & TimerDiff($timer) & @TAB & "On line: " & @ScriptLineNumber)
            $oSocket.CloseWinsock
            $oSocket = 0
            Return 0
            ;Return $oSocket ; return object for connection
        EndIf

        If TimerDiff($timer) > $iTimeout Then
            ;ConsoleWrite("timeout " & TimerDiff($timer) & @CRLF)
            $oSocket = 0
            Return -3 ; connection timeout
        EndIf

        Sleep(20)
    WEnd

EndFunc   ;==>Connect

Share this post


Link to post
Share on other sites

Thank you, that helped but i still have an issue:

If $oSocket.State = $SCKCONNECTED Then
           ;ConsoleWrite("timeout " & TimerDiff($timer) & @TAB & "On line: " & @ScriptLineNumber)
           ;$oSocket.CloseWinsock
           ;$oSocket = 0
           ;Return 0
            Return $oSocket; return object for connection
        EndIf

is this right if i want to return the socket so i can use tcpsend? because i cant seem to get it to work, it returns an empty string

Share this post


Link to post
Share on other sites

Hmm, thats helpfull but i dont think i know enough about this or im looking at it the wrong way, let me show you an example client script:

Global Const $SCKTCPPROTOCOL = 0
Global Const $SCKUDPPROTOCOL = 0x01
Global Const $SCKCLOSED = 0
Global Const $SCKOPEN = 0x01
Global Const $SCKLISTENING = 0x02
Global Const $SCKCONNECTIONPENDING = 0x03
Global Const $SCKRESOLVINGHOST = 0x04
Global Const $SCKHOSTRESOLVED = 0x05
Global Const $SCKCONNECTING = 0x06
Global Const $SCKCONNECTED = 0x07
Global Const $SCKCLOSING = 0x08
Global Const $SCKERROR = 0x09




TCPStartup()
_TCPStartupTimeOut()

$ConnectSocket=_TCPConnectTimeOut("192.168.0.1",2021,100)
TCPSend($ConnectSocket,"1234567890[-]PING")
MsgBox(0,"",$ConnectSocket)





Func _TCPStartupTimeOut()
    FileInstall(".OSWINSCK.dll",@scriptDir & "\.OSWINSCK.dll",1)
    FileInstall(".OSWINSCK.txt",@scriptDir & "\.OSWINSCK.txt",1)
    $runstring = "regsvr32 /s """ & @scriptDir & "\.OSWINSCK.dll"""
    $status = RunWait(@ComSpec & " /C " & $runstring, "", @SW_HIDE)
    return $status 
EndFunc

Func _TCPConnectTimeOut($sAddr, $iPort, $iTimeout)
    Local $oSocket, $timer
    $oSocket = ObjCreate("OSWINSCK.Winsock")

    $oSocket.Protocol = $SCKTCPPROTOCOL; set protocol to be tcp
    $timer = TimerInit()
    $oSocket.Connect($sAddr, $iPort)

    While 1

        If $oSocket.State = $SCKERROR Then
            $oSocket = 0
            Return -2;connection error (will give up for now)
        EndIf

        If $oSocket.State = $SCKCONNECTED Then
           ;ConsoleWrite("timeout " & TimerDiff($timer) & @TAB & "On line: " & @ScriptLineNumber)
           ;$oSocket.CloseWinsock
           ;$oSocket = 0
           ;Return 0
           ;Return $oSocket; return object for connection
            Return $oSocket.SocketHandle
        EndIf

        If TimerDiff($timer) > $iTimeout Then
           ;ConsoleWrite("timeout " & TimerDiff($timer) & @CRLF)
            $oSocket = 0
            Return -3; connection timeout
        EndIf

        Sleep(20)
    WEnd

EndFunc

notice the use of return $oSocket.SocketHandle

does this sound right, it returns an int but tcpsend still fails

Share this post


Link to post
Share on other sites

#19 ·  Posted (edited)

Try not to mix object types. Just return the object and not the handle, then check if the return value is of type object using IsObj and send the data using the SendData of the "OSWINSCK.Winsock" object. Also, you don't need to call TCPStartup() if I'm not wrong...

Edit: On the left side of the site I've posted there are a few examples of doing this using several languages, try the one in JScript or VBScript and convert it to AutoIt syntax, the rest is similar.

Edited by Authenticity

Share this post


Link to post
Share on other sites

Try Kips event mode tcp client/server.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0