Jump to content

TCP UDF, Event driven!


Kip
 Share

Recommended Posts

Ok, you call TCPConnect() and you want to use that socket handle with my UDF.

Besides TCPConnect, do you want to use _TCP_Server_Create or _TCP_Client_Create as well?

Yes; The TCP_Server_Create has already been called earlier in the script, as well as the registering of events (for connecting and recieving). What code will I need to put the socket handle found in TCPConnect() into the Variables used in your UDF, So that the

_TCP_RegisterEvent($hServer, $TCP_RECEIVE, "recieve")

Will run when data is recieved from the sockets which were determined by the TCPConnect()function.

Thx for your help,

Hypoz.

ongoing projects:-firestorm: Largescale P2P Social NetworkCompleted Autoit Programs/Scripts: Variable Pickler | Networked Streaming Audio (in pure autoIT) | firenet p2p web messenger | Proxy Checker | Dynamic Execute() Code Generator | P2P UDF | Graph Theory Proof of Concept - Breadth First search

Link to comment
Share on other sites

So in a server script you want to add TCPConnect() handles (which are clients).

Clients and a server in one script...

You just want to see me yelling again

Ah. That is where youare wrong.

I have already tried this with my own socket array and a While loop to read these 'client' sockets. It works, I JUST WANT TO KNOW THE CODE TO INSERT SOCKETS INTO YOUR SOKET ARRAY! AHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

ongoing projects:-firestorm: Largescale P2P Social NetworkCompleted Autoit Programs/Scripts: Variable Pickler | Networked Streaming Audio (in pure autoIT) | firenet p2p web messenger | Proxy Checker | Dynamic Execute() Code Generator | P2P UDF | Graph Theory Proof of Concept - Breadth First search

Link to comment
Share on other sites

Ah. That is where youare wrong.

I have already tried this with my own socket array and a While loop to read these 'client' sockets. It works, I JUST WANT TO KNOW THE CODE TO INSERT SOCKETS INTO YOUR SOKET ARRAY! AHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

My UDF can't handle both clients and servers in one script.

Edited by Kip
Link to comment
Share on other sites

My UDF can't handle both clients and servers in one script.

I have looked at your Code, theoretically it should work.

ongoing projects:-firestorm: Largescale P2P Social NetworkCompleted Autoit Programs/Scripts: Variable Pickler | Networked Streaming Audio (in pure autoIT) | firenet p2p web messenger | Proxy Checker | Dynamic Execute() Code Generator | P2P UDF | Graph Theory Proof of Concept - Breadth First search

Link to comment
Share on other sites

Hello Kip,

I found this UDF a few months ago and have grown to love using it in most of my scripts. Lately, I've been working on a P2P file sharing program employing this UDF, and I've found after a client sends a large amount of data, the app will no longer accept data from the server, and when you use the _TCP_Client_Stop($hClient) function, It receives the following error:

C:\Program Files\AutoIt3\Include\TCP.au3 (194) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:

TCPCloseSocket($__TCP_SOCKETS[$iElement][0])

TCPCloseSocket(^ ERROR

I was wondering what may be causing this issue, and if there is a workaround or fix. I will post the source if necessary.

Thank you

- Yagerbomb

Link to comment
Share on other sites

Are you using servers and clients in the same script? Because that would be rather stupid and dumb.

Thankfully no, I listened to your first post on not using Servers and Clients in the same script and have followed that rule. Here is a "Smaller" version of a client providing the error:

#include <TCP.au3>
#include <array.au3>
#include <file.au3>

local $hSocket, $hClient, $loIP = @IPAddress1, $ips[1], $Connected = 0, $int = 0, $ServerSocket, $TCP_Send_Buffer, $a_data[1]

Local $sIP = "192.168.1.108" ;Server IP
Local $iPort = 88 ; Server Port

HotKeySet("{F2}", "Disconnect")

$hClient = _TCP_Client_Create($sIP, $iPort)

_TCP_RegisterEvent($hClient, $TCP_CONNECT, "Connected")
_TCP_RegisterEvent($hClient, $TCP_RECEIVE, "Recv")
$Returned = 1

while 1
    sleep(20)
WEnd

Func Connected($hSocket, $iError);Give background data on clients
    $Connected = 1
    ConsoleWrite("Connected" & @CRLF)
    ConsoleWrite('_TCP_Send(' & $hSocket & ', ' & '|00>>' & @IPAddress1 & ")" & @crlf)
    _TCP_Send($hSocket, "|00>>" & @IPAddress1 )
    $TCP_Send_Buffer = "|00>>" & @IPAddress1
    $ServerSocket = $hSocket
    Return($hSocket)
EndFunc

Func Recv($hSocket, $Data, $iError)
    $Returned = 0
    if $iError <> 0 Then
        ConsoleWrite("!Error: " & $iError)
    EndIf
    ConsoleWrite("-Received Data" & @CRLF)
    $d_code = StringRight(StringLeft($Data, 3), 2)
    ConsoleWrite("$d_code =" & $d_code & @CRLF)
    $d_data = StringTrimLeft($Data, 5)
    ConsoleWrite("$d_data =" & $d_data & @CRLF)

    if StringRight($d_code, 1) = ">" Then ; Error Parsing recieved data
        _TCP_Send($hSocket, "|14>>*Resend Request*")
        $TCP_Send_Buffer = "|14>>*Resend Request*"
        Return
    EndIf

    if $d_code = "14" Then ; Recieve error with server
        _TCP_Send($hSocket, $TCP_Send_Buffer)
    EndIf

    if $d_code = "07" Then ; Receive data request
        ;create data
        $n_loop = 0
        while $n_loop <= 100
            $data = Random(0,9, 1)
            ConsoleWrite($n_loop & ": " & $data)
            _ArrayAdd($a_data, $data)
            $a_data[0] += 1
            $n_loop += 1
        WEnd

        $n_loop = 1
        while $n_loop <= $a_data[0]
            _TCP_Send($hSocket, "|08>>" & $a_data[$n_loop])
            $TCP_Send_Buffer = "|08>>" & $a_data[$n_loop]
            ConsoleWrite("|08>>" & $a_data[$n_loop] & @CRLF)
            $n_loop += 1
            if $n_loop > $a_data[0] Then
                sleep(200)
                ConsoleWrite("-Upload Complete" & @CRLF)
                _TCP_Send($hSocket, "|08>>x")
                $TCP_Send_Buffer = "|08>>x"
                Return
            EndIf
            sleep(150)
        WEnd
        Return
    EndIf

EndFunc

Func Disconnect()
    _TCP_Client_Stop($hClient)
    Exit
EndFunc

And here is the paired server script that will result in an error:

#cs
    Nicholas A. Yager
    Server Error
#ce

#include "TCP.au3"
#include <array.au3>

Local $iPort = 88, $sIP = @IPAddress1, $clients[1], $hSocket, $ips[1], $a_data[1]
Local  $TCP_Send_Buffer = "", $File_Resend_Buffer = ""

$ips[0] = 0

ConsoleWrite($sIP & @crlf)

$hServer = _TCP_Server_Create($iPort, $sIP)
ConsoleWrite("-Server Started" & @crlf)

_TCP_RegisterEvent($hServer, $TCP_RECEIVE, "Recv")
_TCP_RegisterEvent($hServer, $TCP_NEWCLIENT, "NewClient")
_TCP_RegisterEvent($hServer, $TCP_DISCONNECT, "Disconnect")


while 1
    sleep(10)
WEnd

Func NewClient($hSocket, $iError)
    ConsoleWrite("-New Client Detected" & @crlf)
    $clients[0] += 1
    _ArrayAdd($clients, $hSocket)
    Return
EndFunc

Func Recv($hSocket, $Data, $iError)
    ConsoleWrite("-Received Data" & @CRLF)
    $d_code = StringRight(StringLeft($Data, 3), 2)
    ConsoleWrite("$d_code =" & $d_code & @CRLF)
    $d_data = StringTrimLeft($Data, 5)
    ConsoleWrite("$d_data =" & $d_data & @CRLF)

    if StringRight($d_code, 1) = ">" Then
        _TCP_Send($hSocket, "|14>>*Resend Request*")
        $TCP_Send_Buffer = "|14>>*Resend Request*"
        Return
    EndIf

    if $d_code = "00" Then ; Receive General Info
        $d_ip_name = StringSplit($d_data, "/", 1)
        $d_ip = $d_ip_name[1]
        ConsoleWrite("IP = " & $d_ip & @crlf)
        _ArrayAdd($ips, $d_ip)
        $ips[0] += 1

        _TCP_Send($hSocket, "|07>>")
        return
    EndIf

    if $d_code = "08" Then
        if $d_data = "x" Then
            _TCP_Send($hSocket, "07>>")
            ConsoleWrite("-Awaiting further data..." & @CRLF)
                        return
        Else
            if StringIsAlNum ( $d_data ) Then
                _ArrayAdd($a_data, $d_data)
                $a_data += 1
            Else
                _TCP_Send($hSocket, "|14>>*Resend Request*")
                $TCP_Send_Buffer = "|14>>*Resend Request*"
            EndIf
        Return
        EndIf

    EndIf

EndFunc

func Disconnect($hSocket, $iError)
    ConsoleWrite("-Client Disconnect Detected: ")
    $ArrayID = _ArraySearch($clients, $hSocket)
    Console

Sorry about how untidy they are, but they were written quickly. This will show the client not accepting network traffic, and on pressing "F2" to disconnect will show the UDF error. I hope this helps.

-Yagerbomb

Link to comment
Share on other sites

Your server script is cut off in the middle of the Disconnect function.

Pardon my mistake. That was just an error copying the code into the web browser. I checked the coding elsewhere and it has the full disconnect function and the udf bug. Here is the corrected server script:

#cs
    Nicholas A. Yager
    Server Error
#ce

#include "TCP.au3"
#include <array.au3>

Local $iPort = 88, $sIP = @IPAddress1, $clients[1], $hSocket, $ips[1], $a_data[1]
Local  $TCP_Send_Buffer = "", $File_Resend_Buffer = ""

$ips[0] = 0

ConsoleWrite($sIP & @crlf)

$hServer = _TCP_Server_Create($iPort, $sIP)
ConsoleWrite("-Server Started" & @crlf)

_TCP_RegisterEvent($hServer, $TCP_RECEIVE, "Recv")
_TCP_RegisterEvent($hServer, $TCP_NEWCLIENT, "NewClient")
_TCP_RegisterEvent($hServer, $TCP_DISCONNECT, "Disconnect")


while 1
    sleep(10)
WEnd

Func NewClient($hSocket, $iError)
    ConsoleWrite("-New Client Detected" & @crlf)
    $clients[0] += 1
    _ArrayAdd($clients, $hSocket)
    Return
EndFunc

Func Recv($hSocket, $Data, $iError)
    ConsoleWrite("-Received Data" & @CRLF)
    $d_code = StringRight(StringLeft($Data, 3), 2)
    ConsoleWrite("$d_code =" & $d_code & @CRLF)
    $d_data = StringTrimLeft($Data, 5)
    ConsoleWrite("$d_data =" & $d_data & @CRLF)

    if StringRight($d_code, 1) = ">" Then
        _TCP_Send($hSocket, "|14>>*Resend Request*")
        $TCP_Send_Buffer = "|14>>*Resend Request*"
        Return
    EndIf

    if $d_code = "00" Then ; Receive General Info
        $d_ip_name = StringSplit($d_data, "/", 1)
        $d_ip = $d_ip_name[1]
        ConsoleWrite("IP = " & $d_ip & @crlf)
        _ArrayAdd($ips, $d_ip)
        $ips[0] += 1

        _TCP_Send($hSocket, "|07>>")
        return
    EndIf

    if $d_code = "08" Then
        if $d_data = "x" Then
            _TCP_Send($hSocket, "07>>")
            ConsoleWrite("-Awaiting further data..." & @CRLF)
            Return
        Else
            if StringIsAlNum ( $d_data ) Then
                _ArrayAdd($a_data, $d_data)
                $a_data += 1
            Else
                _TCP_Send($hSocket, "|14>>*Resend Request*")
                $TCP_Send_Buffer = "|14>>*Resend Request*"
            EndIf
        Return
        EndIf

    EndIf

EndFunc

func Disconnect($hSocket, $iError)
    ConsoleWrite("-Client Disconnect Detected: ")
    $ArrayID = _ArraySearch($clients, $hSocket)
    ConsoleWrite($hSocket & " ")
    _ArrayDelete($clients, $ArrayID)
    ConsoleWrite($ArrayID & " ")
    $clients[0] = $clients[0] - 1
    Return
EndFunc

Sorry about the confusion, and hopefully this will give you the necessary info to progress...

Link to comment
Share on other sites

Pressing F2 shuts down the script perfectly without any errors.

Even after stripping down both scripts to purely TCP stuff, the Connected function still gets called about 20% of all the times I run the client. :blink:

Edit: Removing the array.au3 and file.au3 include files highly increase the number of times the client will connect. I've tested it a lot. With and without, and with again. There is a huge difference. I don't think this has anything to do with my UDF. More likely AutoIt self (or those include files).

Edited by Kip
Link to comment
Share on other sites

  • 2 weeks later...

Is this UDF capable of communicating via TCP Sockets with applications not written in AutoIt? More specifically, does an application not written in AutoIt (c# for example) need to do an event register before it sends data or something of the like?

Link to comment
Share on other sites

Is this UDF capable of communicating via TCP Sockets with applications not written in AutoIt? More specifically, does an application not written in AutoIt (c# for example) need to do an event register before it sends data or something of the like?

It can be used with any language that supports TCP. How that language uses TCP, however, is different for each language. (Although there is a pattern.)

Link to comment
Share on other sites

It can be used with any language that supports TCP. How that language uses TCP, however, is different for each language. (Although there is a pattern.)

I guess a slightly more specific or better question might be this scenario + question:

I used your UDF to write a service that uses TCP Sockets to communicate with other things. I wrote a test application in AutoIt to send commands to the service. Your UDF uses some sort of event registering mechanism to see when messages are received or clients are connected.

If I write a client to send commands to the service in a language like C#, do I have to do some sort of event registering or can I just write data to the TCP Socket and the service will listen to everything written there?

Link to comment
Share on other sites

I kind of doubt this UDF is going to listen to TCP data sent via another socket. Kip creates "registered events" in AutoIt. I put this in quotes because it is important to understand this so people don't try to write a client and server in the same script. Basically, you should be writing your server scripts as a series of functions with NO main script. Then you write your client with a procedural method, meaning, Step 1, Step 2, Step 3, etc. Your server script can't be written in Step 1, Step 2, Step 3 because all it is going to do is listen for a connection and then run something when it gets a connection or when data is being transferred.

This being said, code in C# or C can't be "triggered" when registered events occur in AutoIt without having AutoIt run external programs compiled in C. Additionally, I kind of doubt this is going to listen in on connections you make in other programs, either.

In order to do that sort of thing, you're going to want to look at the AutoIt Pcap library stuff here:

http://opensource.grisambre.net/pcapau3/

Link to comment
Share on other sites

I kind of doubt this UDF is going to listen to TCP data sent via another socket. Kip creates "registered events" in AutoIt.

This being said, code in C# or C can't be "triggered" when registered events occur in AutoIt without having AutoIt run external programs compiled in C. Additionally, I kind of doubt this is going to listen in on connections you make in other programs, either.

You're completely wrong.

I didn't "create the events in AutoIt". What the hell are you talking about?

You can use this UDF to communicate to anything that uses TCP. The language a program is written in has nothing to do with how TCP communicates.

I used your UDF to write a service that uses TCP Sockets to communicate with other things. I wrote a test application in AutoIt to send commands to the service. Your UDF uses some sort of event registering mechanism to see when messages are received or clients are connected.

If I write a client to send commands to the service in a language like C#, do I have to do some sort of event registering or can I just write data to the TCP Socket and the service will listen to everything written there?

You don't HAVE to register events. Just connect to your server, and send something to it.
Link to comment
Share on other sites

You're completely wrong.

I didn't "create the events in AutoIt". What the hell are you talking about?

You can use this UDF to communicate to anything that uses TCP. The language a program is written in has nothing to do with how TCP communicates.

You don't HAVE to register events. Just connect to your server, and send something to it.

Awesome, I was having some doubt as to how my newly created service would be able to communicate with another application but this clears it up -- I thought it worked like this after I looked at it in ProcMon. Thanks

Link to comment
Share on other sites

I am having problems getting this to run in Windows XP.

I tried even using the examples and the server gets stuck (meaning the tooltip stays up) on the creating server part.

Any ideas on why this might be? Needs files or needs updated or something?

Edit: I was mistaken, the example client server scripts work, but mine doesn't. Looks like I need to dig in and find out.

Edit 2: I went through all of my code and rewrote everything only to figure out that my server works fine. The problem is that the client isn't detecting that it got connected, but the server did. Not sure why the client isn't connecting properly in my code, but it works well enough to use.

Edited by cvocvo
Link to comment
Share on other sites

  • 1 month later...

Hi there,

i'm wondering if theres a need to unregister events before recreating new ones.

in my test client, i can get disconnected.

By clicking on a button, I can reconnect.

it's calling the 'connect()' function which calls the _TCP_Client_Create function and Registers 3 events (Connect, Disconnect & Receive).

The problem is that the Connect Event is not triggered when I reconnect my client.

Do I have to unregister event in some way ?

Heres is my code (its just a client which purpose is testing my server) :

#include <TCP.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <StaticConstants.au3>

GUICreate("Network Test - Client", 500, 200, -1, -1)
Global $GUI_Messages = GUICtrlCreateEdit("en attente d'une action", 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()
    Global $hclient
    ConsoleWrite("hclient avant TCP_Client_Create=" & $hclient & @CRLF)
    Global $hClient = _TCP_Client_Create(@IPAddress1, 37601); Create the client. Which will connect to the local ip address on port 88
    ConsoleWrite("hclient apres TCP_Client_Create=" & $hclient & @CRLF)
    _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.
    _TCP_RegisterEvent($hClient, $TCP_RECEIVE, "Received"); Function "Received" will get called when something is received
EndFunc

While 1
    $msg = GUIGetMsg()
    Select
        Case $msg = $GUI_EVENT_CLOSE
            Exit
        Case $msg = $GUI_Button_Send1
            Connect()
        Case $msg = $GUI_Button_Send2
            ConsoleWrite("envoi au serveur !" & @CRLF)
            GUICtrlSetData($GUI_Messages, @CRLF & "Tentative d'identification", 1)
            If Not TCPSend($hclient,"2569EA0F69A71DD56BD87750|#A01") Then GUICtrlSetData($GUI_Messages, @CRLF & "Echec de l'envoi - wsa error:" & @error, 1)
    EndSelect
WEnd


Func Connected($hSocket, $iError); We registered this (you see?), When we're connected (or not) this function will be called.
ConsoleWrite("appel de la fonction 'connected()'" & @crlf)
    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)
    ConsoleWrite("appel de la fonction Received()" & @CRLF)
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

I still have the same problem.

Once the 'Connected' event triggered a first time, and if the client disconnects for a reason, any other call of the Connect function will not trigger the 'Connected' event again.

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