Jump to content

TCP UDF, Event driven!


Kip
 Share

Recommended Posts

The error still exists in the stable version.

I'm running using the same code as above.

It failed when around 115 connections were made.

>Running:(3.3.0.0):C:\Program Files\AutoIt3\autoit3.exe "X:\Scripts\Update System\Monitor\Server - Updater.au3"    
C:\Program Files\AutoIt3\Include\TCP.au3 (386) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:
If $__TCP_SOCKETS[$i][0] Then
If ^ ERROR
Edited by kjcdude
Link to comment
Share on other sites

  • 2 weeks later...

Yeah. I made something like that, but it wasn't optimized. It didn't have much error checking and wasn't in udf form. I think it would help out some beginners and make your udf more complete.

Edited by dantay9
Link to comment
Share on other sites

  • 4 weeks later...

I've been really busy and only recently have had the time to come back around to this problem.

It still fails running 3.3.1.4

I went ahead and had TCP.au3 generate a log of everything happening inside _TCP_Server_ClientList().

Here's the updated code with the log being written.

Func _TCP_Server_ClientList()

    Local $aReturn[1], $i

    For $i = 1 to UBound($__TCP_SOCKETS)-1
        FileWriteLine($fhandle, "$i = " & $i)
        FileWriteLine($fhandle, "UBound = " & UBound($__TCP_SOCKETS)-1)
        FileWriteLine($fhandle, "__TCP_SOSCKETS = " & $__TCP_SOCKETS[$i][0])
        If $__TCP_SOCKETS[$i][0] Then
            ReDim $aReturn[UBound($aReturn)+1]
            $aReturn[UBound($aReturn)-1] = $__TCP_SOCKETS[$i][0]
        EndIf
    Next

    $aReturn[0] = UBound($aReturn)-1

    Return $aReturn

EndFunc

Here's the last 50 lines of the log file.

There were around 150 connections before it failed.

$i = 126

UBound = 141

__TCP_SOCKETS = 84

$i = 127

UBound = 141

__TCP_SOCKETS = 72

$i = 128

UBound = 141

__TCP_SOCKETS = 60

$i = 129

UBound = 141

__TCP_SOCKETS = 48

$i = 130

UBound = 141

__TCP_SOCKETS = 36

$i = 131

UBound = 141

__TCP_SOCKETS = 24

$i = 132

UBound = 141

__TCP_SOCKETS = 12

$i = 133

UBound = 141

__TCP_SOCKETS = 2052

$i = 134

UBound = 141

__TCP_SOCKETS = 2064

$i = 135

UBound = 141

__TCP_SOCKETS = 2076

$i = 136

UBound = 141

__TCP_SOCKETS = 2088

$i = 137

UBound = 141

__TCP_SOCKETS = 2100

$i = 138

UBound = 141

__TCP_SOCKETS = 2112

$i = 139

UBound = 141

__TCP_SOCKETS = 2124

$i = 140

UBound = 141

__TCP_SOCKETS = 2136

$i = 141

UBound = 141

__TCP_SOCKETS = 2148

$i = 142

UBound = 141

Here's the last lines of another log.

$i = 80

UBound = 84

__TCP_SOCKETS = 504

$i = 81

UBound = 84

__TCP_SOCKETS = 492

$i = 82

UBound = 84

__TCP_SOCKETS = 480

$i = 83

UBound = 84

__TCP_SOCKETS = 468

$i = 84

UBound = 84

__TCP_SOCKETS = 456

$i = 85

UBound = 84

It looks like the issue is with the $i and UBound Edited by kjcdude
Link to comment
Share on other sites

  • 2 weeks later...

Seems like an AutoIt bug then. I don't see how $i can get larger than Ubound()-1

Maybe an AutoIt, but maybe not. The max value of the For loop is fixed, But Ubound() could be changed:

Func _TCP_Server_ClientList()

Local $aReturn[1], $i

;This line sets the max value of the for loop to UBound($__TCP_SOCKETS)-1

For $i = 1 to UBound($__TCP_SOCKETS)-1

;

; Some parts of your UDF are working asynchoniusly. What happens if the count of elements in $__TCP_SOCKETS is changed by an asynchron running function just before executing the next line?

;

FileWriteLine($fhandle, "$i = " & $i)

FileWriteLine($fhandle, "UBound = " & UBound($__TCP_SOCKETS)-1)

FileWriteLine($fhandle, "__TCP_SOSCKETS = " & $__TCP_SOCKETS[$i][0])

If $__TCP_SOCKETS[$i][0] Then

ReDim $aReturn[uBound($aReturn)+1]

$aReturn[uBound($aReturn)-1] = $__TCP_SOCKETS[$i][0]

EndIf

Next

$aReturn[0] = UBound($aReturn)-1

Return $aReturn

EndFunc

I'm not shure if enumerating an array is the best way. Maybe using sqlite is a alternative to manage the connections and handles?

Best wishes

Paul

Link to comment
Share on other sites

@kjcDude:

Does it work when you replace _TCP_Server_ClientList from the UDF with this version?:

Func _TCP_Server_ClientList()
    
    Local $aReturn[1], $i
    
    local $aSocketsCopy = $__TCP_SOCKETS
    
    For $i = 1 To UBound($aSocketsCopy) - 1
        If $aSocketsCopy[$i][0] Then
            ReDim $aReturn[UBound($aReturn) + 1]
            $aReturn[UBound($aReturn) - 1] = $aSocketsCopy[$i][0]
        EndIf
    Next
    
    $aReturn[0] = UBound($aReturn) - 1
    
    Return $aReturn
    
EndFunc ;==>_TCP_Server_ClientList
Link to comment
Share on other sites

@kjcDude:

Does it work when you replace _TCP_Server_ClientList from the UDF with this version?:

Func _TCP_Server_ClientList()
    
    Local $aReturn[1], $i
    
    local $aSocketsCopy = $__TCP_SOCKETS
    
    For $i = 1 To UBound($aSocketsCopy) - 1
        If $aSocketsCopy[$i][0] Then
            ReDim $aReturn[UBound($aReturn) + 1]
            $aReturn[UBound($aReturn) - 1] = $aSocketsCopy[$i][0]
        EndIf
    Next
    
    $aReturn[0] = UBound($aReturn) - 1
    
    Return $aReturn
    
EndFunc ;==>_TCP_Server_ClientList

Jepp, the first test seems to be successful.

I will do some other test and report the results here.

Anyone else testing this new version of _TCP_Server_ClientList?

Best wishes

Paul

Edited by PaulBaumann
Link to comment
Share on other sites

  • 2 weeks later...

Initial tests looks great, no failures so far.

Running with 200 concurrent connections, everything is reporting correctly.

I'm going to run my full version of the program on 5 servers next week. I'll report back with some more real world results.

Thanks for the fix!

Link to comment
Share on other sites

I'm a bit of a newbie to autoit, I've had a go at modifying your example script a bit and I'm trying to get a function to TCP_Send from the Server to the Client but cant seem to get the Function call when you press a button (I've tried many different combos). The whole custom params thing using a UDF confuses me if theres any good tutorial/read up please share!

Heres the Server script:

#include <TCP.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <StaticConstants.au3>
  
GUICreate("Network Test - Server", 500, 200, -1, -1)
$GUI_Messages = GUICtrlCreateEdit("Server Starting...", 120, 10, 370, 180, $ES_AUTOVSCROLL + $WS_VSCROLL + $ES_READONLY)
GUICtrlSetBkColor ($GUI_Messages, 0xffffff)
$GUI_Button_Send1 = GUICtrlCreateButton("Broadcast", 10, 10, 100, 30)
$GUI_Button_Send2 = GUICtrlCreateButton("Clients", 10, 50, 100, 30)
$GUI_Button_Send3 = GUICtrlCreateButton("Send Message", 10, 90, 100, 30)

GUISetState()
  
$hServer = _TCP_Server_Create(1008); A server. Tadaa!
GUICtrlSetData($GUI_Messages, @CRLF & "Server Running" , 1)
_TCP_RegisterEvent($hServer, $TCP_NEWCLIENT, "NewClient"); Whooooo! Now, this function (NewClient) get's called when a new client connects to the server.
_TCP_RegisterEvent($hServer, $TCP_DISCONNECT, "Disconnect"); And this,... this will get called when a client disconnects.
_TCP_RegisterEvent($hServer, $TCP_SEND, "SendMessage")
  
Func NewClient($hSocket, $iError); Yo, check this out! It's a $iError parameter! (In case you didn't noticed: It's in every function)
    GUICtrlSetData($GUI_Messages, @CRLF & "Client Connected", 1)
    _TCP_Send($hSocket, "Bleh!"); Sending: "Bleh!" to the new client. (Yes, that's right: $hSocket is the socket of the new client.)
EndFunc
  
Func Disconnect($hSocket, $iError); Damn, we lost a client. Time of death: @Hour & @Min & @Sec :P
    GUICtrlSetData($GUI_Messages, @CRLF & "Client Disconnected", 1)
EndFunc

Func BroadCast1($hSocket, $iError)
    $clients = _TCP_Server_ClientList()
    GUICtrlSetData($GUI_Messages, $clients, 1)
    MsgBox( 1, "asd", $clients)
EndFunc

Func SendMessage($hSocket, $iError)
    GUICtrlSetData($GUI_Messages, @CRLF & "Sent Message: Jebus", 1)
    _TCP_Send($hSocket, "Bleh!")
    MsgBox( 1, "asd", "Message Sent")
EndFunc

While 1
    $msg = GUIGetMsg()
    Select
        Case $msg = $GUI_EVENT_CLOSE
            Exit
        Case $msg = $GUI_Button_Send1
        Case $msg = $GUI_Button_Send2
            _TCP_RegisterEvent($hServer, $TCP_SEND, "SendMessage")
        Case $msg = $GUI_Button_Send3
    EndSelect
WEnd

Client script:

#include <TCP.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <StaticConstants.au3>
     
GUICreate("Network Test - Client", 500, 200, -1, -1)
$GUI_Messages = GUICtrlCreateEdit("Connecting...", 120, 10, 370, 180, $ES_AUTOVSCROLL + $WS_VSCROLL + $ES_READONLY)
GUICtrlSetBkColor ($GUI_Messages, 0xffffff)
$GUI_Button_Send1 = GUICtrlCreateButton("Connect", 10, 10, 100, 30)
$GUI_Button_Send2 = GUICtrlCreateButton("Send2", 10, 50, 100, 30)
     
GUISetState()

Func Connect()
    $hClient = _TCP_Client_Create(@IPAddress1, 1008); Create the client. Which will connect to the local ip address on port 88
    _TCP_RegisterEvent($hClient, $TCP_RECEIVE, "Received"); Function "Received" will get called when something is received
    _TCP_RegisterEvent($hClient, $TCP_CONNECT, "Connected"); And func "Connected" will get called when the client is connected.
    _TCP_RegisterEvent($hClient, $TCP_DISCONNECT, "Disconnected"); And "Disconnected" will get called when the server disconnects us, or when the connection is lost.
EndFunc

While 1
    $msg = GUIGetMsg()
    Select
        Case $msg = $GUI_EVENT_CLOSE
            Exit
        Case $msg = $GUI_Button_Send1
            Call("Connect")
        Case $msg = $GUI_Button_Send2
    EndSelect
WEnd

     
Func Connected($hSocket, $iError); We registered this (you see?), When we're connected (or not) this function will be called.
         
    If not $iError Then; If there is no error...
        GUICtrlSetData($GUI_Messages, @CRLF & "Connected to Server", 1); ... we're connected.
    Else; ,else...
        GUICtrlSetData($GUI_Messages, @CRLF & "Could not Connect", 1); ... we aren't.
    EndIf
EndFunc

     
Func Received($hSocket, $sReceived, $iError); And we also registered this! Our homemade do-it-yourself function gets called when something is received.
    GUICtrlSetData($GUI_Messages, @CRLF & $sReceived, 1) ;(and we'll display it)
EndFunc
     
Func Disconnected($hSocket, $iError); Our disconnect function. Notice that all functions should have an $iError parameter.
    GUICtrlSetData($GUI_Messages, @CRLF & "Connection Lost", 1)
EndFunc

Any help appreciated!

Edited by Valley
Link to comment
Share on other sites

Hi Kip and First : Great job to you and others contributors.

i'm trying to use your UDF in a client/Server oriented update program.

I would like to know if there's is a way to prevent an already connected client to reconnects the server. At this time, theres no protection.

I could implement an IP-based protection with an 2D array filled during every call of the Connected() func with the socket and its IP but I don't like the fact to maintain another array.

is there a way to add the socket's IP to the TCP_SOCKETS array in your udf. That way i could get it when I call TCP_Server_ClientList().

Thanks for your remarks

Link to comment
Share on other sites

Initial tests looks great, no failures so far.

Running with 200 concurrent connections, everything is reporting correctly.

I'm going to run my full version of the program on 5 servers next week. I'll report back with some more real world results.

Thanks for the fix!

I ran it live on 5 servers on Tuesday night and ran into no issues. Each server was handling about 160 clients with no issue.

Thanks for the fix!

Link to comment
Share on other sites

Hi Kip and First : Great job to you and others contributors.

i'm trying to use your UDF in a client/Server oriented update program.

I would like to know if there's is a way to prevent an already connected client to reconnects the server. At this time, theres no protection.

I could implement an IP-based protection with an 2D array filled during every call of the Connected() func with the socket and its IP but I don't like the fact to maintain another array.

is there a way to add the socket's IP to the TCP_SOCKETS array in your udf. That way i could get it when I call TCP_Server_ClientList().

Thanks for your remarks

No, you'd have to modify large parts of the UDF then.

Link to comment
Share on other sites

I have the server send back whatever it receives and the client puts it into a log. I also had the client msgbox whatever it was sending. If one client receives a "" back from the server I open a new client with the same results. If I restart the server the clients can send data again. So what do you think is the cause of the server not being able to accept tcp data from any clients is?

People really should start posting example scripts...:)

How the hell am I supposed to know whats wrong if I don't even have a small piece of script that reproduces the 'bug'?

Edited by Kip
Link to comment
Share on other sites

People really should start posting example scripts...:)

How the hell am I supposed to know whats wrong if I don't even have a small piece of script that reproduces the 'bug'?

To the user who reported Kip's post (quoted) as offensive: Fuck off. There's nothing offensive about his post and its borderline "abuse of the Report feature" to mark it as such.

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...