Jump to content

TCPClient UDF (multi client, event-based, able to bind console app to socket)


Jefrey
 Share

Recommended Posts

Hi!

If you liked my TCPServer UDF, you'll also like this one.

Following the same principles, this TCPClient UDF helps you on handling multiple connections to different servers, and set actions depending on two events: OnReceive and OnDisconnect.

It is also multi server (you can connect to many servers at once) and you can also bind a Console-based executable to the socket (similar to -e parameter in NetCat). This feature is useful if you want to use some Console UDF to create a TCP application and don't want to deal with the TCP* functions. Also, it runs on background just firing events, it won't pause your script while waiting/receiving data, so you can do anything else (close and open connections, allow the user to click buttons or just wait on an infinite loop) that your callbacks will be called once the event is fired

It is also very easy to use. See this examples:

Example #1: Connecting to a basic server

By running this (as soon as you open a basic server with Netcat) you will receive a message box telling you when the server closes the connection (the socket ID and his IP address are passed as parameter to your callback function) and also when the server sends something over the TCP socket (the data sent is passed as parameter).

#cs
    Download netcat at https://eternallybored.org/misc/netcat/
    Execute this script
    Run in CMD:
    nc -vv -l -p 8081
#ce

#include "TCPClient.au3"

; First we set the callback functions for the two events (none of them is mandatory)
_TCPClient_OnDisconnect("disconnect")
_TCPClient_OnReceive("received")

; And a parameter
_TCPClient_DebugMode(True)

; Finally we connect to the server at port 8081 at any interface
_TCPClient_Connect('127.0.0.1', 8081)

Func disconnect($iSocket, $sIP)
    MsgBox(0, "Server disconnected", "Server " & $sIP & " disconnected from socket " & $iSocket)
EndFunc   ;==>disconnect

Func received($iSocket, $sIP, $sData, $sPar)
    MsgBox(0, "Data received from " & $sIP, $sData & @CRLF & "Parameter: " & $sPar)
    _TCPClient_Send($iSocket, "You wrote: " & $sData)
    _TCPClient_SetParam($iSocket, 'will write again')
EndFunc   ;==>received

While 1
    Sleep(100)
WEnd

Example #2: Requesting a page from a HTTP server

In this example, we run this code and it will get the response from a HTTP server. Of course, as we are requesting google.com index, it may just show a redirect page to a local (with country top-level domain) Google page or with some stuff on the URL.

#include "TCPClient.au3"

_TCPClient_OnReceive("received")

_TCPClient_DebugMode(True)

$iSocket = _TCPClient_Connect(TCPNameToIP('google.com'), 80)

If @error Then Exit

_TCPClient_Send($iSocket, "GET / HTTP/1.0" & @CRLF & @CRLF)


Func received($iSocket, $sIP, $sData, $sParam)

    MsgBox(0, "Data received", $sData)
    _TCPClient_Disconnect($iSocket)

EndFunc   ;==>received

While 1
    Sleep(100)
WEnd

Example #3: Command prompt bound to the socket after password requesting

By running this example, we will be asked for a password, which is 123456 as we set on the script. If the password is correct, we will see the Command Prompt live-updated (try running a ping to some server, for example).

#include "TCPClient.au3"

#cs
    To test this example,
    execute a netcat server,
    running this commands:
    nc -vv -l -p 31337
#ce

Global $Password = "123456"

_TCPClient_OnReceive("receive")
_TCPClient_OnDisconnect("disconnect")

_TCPClient_DebugMode()

Func receive($iSocket, $sIP, $sData, $mPar)
    If $mPar = "login" Then
        If $sData = $Password Then
            ; right password, let's change the parameter
            _TCPClient_SetParam($iSocket, "logged")

            ; and now bind
            _TCPClient_BindAppToSocket($iSocket, "cmd.exe")

        Else
            _TCPClient_Send($iSocket, "Wrong password. Try again: ")
        EndIf
    Else
        If $sData = "exit" Then
            ; unbinds
            _TCPClient_UnBindAppToSocket($iSocket)

            ; says bye
            _TCPClient_Send($iSocket, "See you")

            ; closes connection
            _TCPClient_Disconnect($iSocket)
        Else
            ; sends command directly to the process
            _TCPClient_SendToBound($iSocket, $sData)
        EndIf
    EndIf
EndFunc

Func disconnect($iSocket, $sIP)
    MsgBox(0, $iSocket, $sIP)
EndFunc

$iSocket = _TCPClient_Connect('127.0.0.1', '31337')

If @error Then
    MsgBox(0, "", "could not connect. Error: " & @error)
    Exit
EndIf

; Sets parameter to login, so we know what the server is doing
_TCPClient_SetParam($iSocket, "login")

_TCPClient_Send($iSocket, "Please enter password: ")

While True
    Sleep(100)
WEnd

The limit is your imagination? Well, maybe.

Functions list:

  • _TCPClient_Connect($sSvr, $iPort)
    _TCPClient_Disconnect($iSocket)
    _TCPClient_SetParam($iSocket, $sPar)
    _TCPClient_Send($iSocket, $sData)
    _TCPClient_Broadcast($sData [, $iExceptSocket = 0 ])
    _TCPClient_ListConnections()
    _TCPClient_BindAppToSocket($iSocket, $sCommand [, $sWorkingDir = @WorkingDir ])
    _TCPClient_SendToBound($iSocket, $sData)
    _TCPClient_UnBindAppToSocket($iSocket)
    _TCPClient_OnReceive($sCallback)
    _TCPClient_OnDisconnect($sCallback)
    _TCPClient_DebugMode([ $bMOde = "toggle" ])
    _TCPClient_AutoTrim([ $bMode = "toggle" ])
    _TCPClient_SocketToConnID($iSocket)
    _TCPClient_ConnIDToSocket($iConn)
    _TCPClient_SocketToIP($iSocket)

Help file and more examples included!

Latest version: 1.0.0

Download: https://www.autoitscript.com/forum/files/file/377-tcpclient-udf/

Changelog

  • 1.0.0 - First release - 03/12/2015

If you can't open the help file, please uncompress it, go to properties and click Unlock.

Fork me on Github: http://github.com/jesobreira/tcpclient-udf 

Edited by Jefrey

My stuff

Spoiler

My UDFs  _AuThread multithreading emulation for AutoIt · _ExtInputBox an inputbox with multiple inputs and more features · forceUTF8 fix strings encoding without knowing its original charset · JSONgen JSON generator · _TCPServer UDF multi-client and multi-task (run on background) event-based TCP server easy to do · _TCPClient_UDF multi-server and multi-task (runs on background) event-based TCP client easy to do · ParseURL and ParseStr functions ported from PHP · _CmdLine UDF easily parse command line parameters, keys or flags · AutoPHP Create documents (bills, incomes) from HTML by sending variables/arrays from AutoIt to PHP · (Un)Serialize Convert arrays and data into a storable string (PHP compatible) · RTTL Plays and exports to MP3 Nokia-format monophonic ringtones (for very old cellphones) · I18n library Simple and easy to use localization library · Scripting.Dictionary OOP and OOP-like approach · Buffer/stack limit arrays to N items by removing the last one once the limit is reached · NGBioAPI UDF to work with Nitgen fingerprint readers · Serial/Licensing system require license key based on unique machine ID from your users · HTTP a simple WinHTTP library that allows GET, POST and file uploads · Thread true AutoIt threads (under-dev) · RC4 RC4 encryption compatible with PHP and JS ·  storage.au3 localStorage and sessionStorage for AutoIt Classes _WKHtmlToX uses wkhtmlto* to convert HTML files and webpages into PDF or images (jpg, bmp, gif, png...) Snippets _Word_DocFindReplaceByLongText replace strings using Word UDF with strings longer than 255 characters (MSWord limit) rangeparser parser for printing-like pages interval (e.g.: "1,2,3-5") EnvParser parse strings/paths with environment variables and get full path GUICtrlStaticMarquee static text scrolling Random stuff Super Mario beep sound your ears will hurt

 

Link to comment
Share on other sites

  • 1 year later...

HI Jefrey and thanks for sharing this UDF
Currently I'm at the beginning on experimenting stuff,


looking in to "example list clients.au3"
I need some basic example on how to make the server respond when it\I needs to send an HTML (a linked form) to the a clients browsers request
Then finally when the form is submitted, the form will post back some data to the server which is what I want to eventually post\send back to the client script
Can you give an example how it can be started off using "example list clients.au3"

TIA

Link to comment
Share on other sites

Hi, @Deye!

Actually what you are trying to do is to create a HTTP server. Note that this UDF supports TCP protocol in a generic state. This means that while you can of course create a HTTP server with it, you will not find everything ready to use as it just takes care about the network part.

Sending the form is as easy as: https://github.com/jesobreira/TCPServerUDF/blob/master/example HTTP Server.au3#L20 (notice the HTML on the lines 20-23).

However for parsing the user request as well as form data, you will need to handle and parse the HTTP headers sent by the browser. It's not something so hard to understand, but depending on what you want to offer, it's a bite of work. Basically it's just string parsing, nothing that you won't solve with a few StringSplit()s, comparisons and regexp - but a lot of them.

If you want to create a full-featured webserver (good luck!), I suggest you to read the HTTP specs: https://www.w3.org/Protocols/Specs.html

If what you want is something simple, I suggest you to use Chrome Dev Tools (Ctrl + Shift + J), go to "Network" tab and get familiarized with the HTTP headers sent and received by the browser. You'll see that it's not hard at all. Using a sniffer (Smartsniff or Socketsniff, or even Wireshark although it might be too advanced for simple analysis) against your browser is also very learningful; you can see how the headers and HTML are sent.

If you need any further help feel free to comment on this thread!

My stuff

Spoiler

My UDFs  _AuThread multithreading emulation for AutoIt · _ExtInputBox an inputbox with multiple inputs and more features · forceUTF8 fix strings encoding without knowing its original charset · JSONgen JSON generator · _TCPServer UDF multi-client and multi-task (run on background) event-based TCP server easy to do · _TCPClient_UDF multi-server and multi-task (runs on background) event-based TCP client easy to do · ParseURL and ParseStr functions ported from PHP · _CmdLine UDF easily parse command line parameters, keys or flags · AutoPHP Create documents (bills, incomes) from HTML by sending variables/arrays from AutoIt to PHP · (Un)Serialize Convert arrays and data into a storable string (PHP compatible) · RTTL Plays and exports to MP3 Nokia-format monophonic ringtones (for very old cellphones) · I18n library Simple and easy to use localization library · Scripting.Dictionary OOP and OOP-like approach · Buffer/stack limit arrays to N items by removing the last one once the limit is reached · NGBioAPI UDF to work with Nitgen fingerprint readers · Serial/Licensing system require license key based on unique machine ID from your users · HTTP a simple WinHTTP library that allows GET, POST and file uploads · Thread true AutoIt threads (under-dev) · RC4 RC4 encryption compatible with PHP and JS ·  storage.au3 localStorage and sessionStorage for AutoIt Classes _WKHtmlToX uses wkhtmlto* to convert HTML files and webpages into PDF or images (jpg, bmp, gif, png...) Snippets _Word_DocFindReplaceByLongText replace strings using Word UDF with strings longer than 255 characters (MSWord limit) rangeparser parser for printing-like pages interval (e.g.: "1,2,3-5") EnvParser parse strings/paths with environment variables and get full path GUICtrlStaticMarquee static text scrolling Random stuff Super Mario beep sound your ears will hurt

 

Link to comment
Share on other sites

Thank you Jefrey,

I was looking for something simple as possible
All I'm wishing to do is host a linked form (not mine) with a webhook addressed to http://MyScriptTCPListener.ddns.net:55555 that is to send me the submitted form's filled data

The linked form (embedded style) contains 
index.html -> file
css        -> folder
js         -> folder

The problem thing left for me is to reveal the sent data sent from the form's webhook tool
https://www.autoitscript.com/forum/topic/189648-content-type-multipart/

I was told that it can be done with having the webhook directed to a simple php script
But I'm not sure how, if its possible to direct the server listener script to the php script file (While when using TCPListen())

However I'd still prefer having the data revealed with autoit code

Thanks
 

Edited by Deye
Link to comment
Share on other sites

Hi @Deye,

As I said this is a TCP Server library, not a HTTP Server library (HTTP is a specified protocol inside TCP). With this library you can create servers of virtually any protocol, although of course you must follow the specs of the creators of the protocol you want to recreate (or even create your own protocol). Depending on the protocol specs, it can demand more or less work.

I've wrote a simple example of form data getting using just this library, easy to adapt to your needs. However when developing any kind of server of any protocol, be 100% sure you're able to code it on a secure way (hackers do exist and are around).

#cs
    Run this script
    Point your browser to http://localhost:8081/
#ce

#include "TCPServer.au3"

_TCPServer_OnReceive("received")

_TCPServer_DebugMode(True)
_TCPServer_SetMaxClients(10)

_TCPServer_Start(8081)


Func received($iSocket, $sIP, $sData, $sParam)
    $sMethod = StringLeft($sData, StringInStr($sData, " ")-1) ; the first header comes in the format: GET / HTTP/1.1 or POST / HTTP/1.1
    $sFile = StringLeft($sData, StringInStr($sData, " ", 2)) ; this is to get the file (after the method - /) - we will not use on this sample but it is useful

    If $sMethod = "GET" Then
        _TCPServer_Send($iSocket, "HTTP/1.0 200 OK" & @CRLF & _         ; HTTP headers
                        "Content-Type: text/html" & @CRLF & @CRLF & _   ; plus 2 line breaks
                        "<h1>Form example</h1>" & @CRLF & _             ; then HTML code
                        "<form method=""post"">" & @CRLF & _
                        "<input type=""text"" name=""test"" placeholder=""Type something"" />" & @CRLF & _
                        "<input type=""number"" name=""somenumber"" placeholder=""Number"" />" & @CRLF & _
                        "<input type=""submit"">" & @CRLF & _
                        "</form>")

        ; you could even send a file:
        #cs
        _TCPServer_Send($iSocket, "HTTP/1.0 200 OK" & @CRLF & _         ; HTTP headers
                        "Content-Type: text/html" & @CRLF & @CRLF & _   ; plus 2 line breaks
                        FileRead("yourfile.html"))
        #ce

        _TCPServer_Close($iSocket)

    ElseIf $sMethod = "POST" Then
        ; the form data is at the last line of the request data, URL encoded
        $sFormdata = StringSplit($sData, @CRLF)
        $sFormdata = $sFormdata[$sFormdata[0]] ; get last line

        ; parse the data
        $aData = ParseStr($sFormdata)

        ; sends some headers plus 2 line breaks as http specs says
        ; (browsers understand 2 line breaks as the separation between headers and HTML code)
        _TCPServer_Send($iSocket, "HTTP/1.0 200 OK" & @CRLF & _         ; HTTP headers
                        "Content-Type: text/html" & @CRLF & @CRLF)  ; plus 2 line breaks

        ; sends some HTML code
        _TCPServer_Send($iSocket, "<!DOCTYPE html>" & @CRLF)
        _TCPServer_Send($iSocket, "<html>" & @CRLF)
        _TCPServer_Send($iSocket, "<body>" & @CRLF)
        _TCPServer_Send($iSocket, "<h1>Form data</h1>" & @CRLF)
        _TCPServer_Send($iSocket, "<ul>" & @CRLF)
        ; shows user data on the page
        For $i = 1 To $aData[0][0]
            ; protects against XSS vulnerability
            $sKey = htmlspecialchars($aData[$i][0])
            $sValue = htmlspecialchars($aData[$i][1])

            _TCPServer_Send($iSocket, "<li><b>" & $sKey & ":</b> " & $sValue & "</li>" & @CRLF)
        Next

        ; ends sending html
        _TCPServer_Send($iSocket, "<a href=""/"">Go back</a>" & @CRLF)
        _TCPServer_Send($iSocket, "</body>" & @CRLF)
        _TCPServer_Send($iSocket, "</html>")

        ; closes socket
        _TCPServer_Close($iSocket)
    EndIf
EndFunc   ;==>received

While 1
    Sleep(100)
WEnd

; =========== internal use only ==============

#cs
    @author Jefrey
    @link https://www.autoitscript.com/forum/topic/188052-phps-parse_url-and-parse_str-ported-to-autoit3/
#ce
Func ParseStr($sStr)
    Local $aExplode = StringSplit($sStr, "&"),$aExplode2
    Local $aResult[$aExplode[0]+1][2]
    For $i = 1 To $aExplode[0]
        $aExplode2 = StringSplit($aExplode[$i], "=")
        $aResult[$i][0] = $aExplode2[1]
        $aResult[$i][1] = $aExplode2[2]

        ; URL decode
        $aResult[$i][1] = StringReplace($aResult[$i][1], "+", " ")
        Local $matches = StringRegExp($aResult[$i][1], "\%([abcdefABCDEF0-9]{2})", 3)
        If IsArray($matches) Then
            For $match In $matches
                $aResult[$i][1] = StringReplace($aResult[$i][1], "%" & $match, BinaryToString('0x' & $match))
            Next
        EndIf
    Next
    $aResult[0][0] = $aExplode[0]
    Return $aResult
EndFunc

#cs
    @author Jefrey
    very basic work based on php.net/htmlspecialchars
#ce

Func htmlspecialchars($sStr)
    $sStr = StringReplace($sStr, '&', '&amp;')
    $sStr = StringReplace($sStr, '"', '&quot;')
    $sStr = StringReplace($sStr, "'", "&apos;")
    $sStr = StringReplace($sStr, "<", "&lt;")
    $sStr = StringReplace($sStr, ">", "&gt;")
    Return $sStr
EndFunc

 

My stuff

Spoiler

My UDFs  _AuThread multithreading emulation for AutoIt · _ExtInputBox an inputbox with multiple inputs and more features · forceUTF8 fix strings encoding without knowing its original charset · JSONgen JSON generator · _TCPServer UDF multi-client and multi-task (run on background) event-based TCP server easy to do · _TCPClient_UDF multi-server and multi-task (runs on background) event-based TCP client easy to do · ParseURL and ParseStr functions ported from PHP · _CmdLine UDF easily parse command line parameters, keys or flags · AutoPHP Create documents (bills, incomes) from HTML by sending variables/arrays from AutoIt to PHP · (Un)Serialize Convert arrays and data into a storable string (PHP compatible) · RTTL Plays and exports to MP3 Nokia-format monophonic ringtones (for very old cellphones) · I18n library Simple and easy to use localization library · Scripting.Dictionary OOP and OOP-like approach · Buffer/stack limit arrays to N items by removing the last one once the limit is reached · NGBioAPI UDF to work with Nitgen fingerprint readers · Serial/Licensing system require license key based on unique machine ID from your users · HTTP a simple WinHTTP library that allows GET, POST and file uploads · Thread true AutoIt threads (under-dev) · RC4 RC4 encryption compatible with PHP and JS ·  storage.au3 localStorage and sessionStorage for AutoIt Classes _WKHtmlToX uses wkhtmlto* to convert HTML files and webpages into PDF or images (jpg, bmp, gif, png...) Snippets _Word_DocFindReplaceByLongText replace strings using Word UDF with strings longer than 255 characters (MSWord limit) rangeparser parser for printing-like pages interval (e.g.: "1,2,3-5") EnvParser parse strings/paths with environment variables and get full path GUICtrlStaticMarquee static text scrolling Random stuff Super Mario beep sound your ears will hurt

 

Link to comment
Share on other sites

Sorry I couldn't get back to this earlier, something came up and had to be away
I see now that the page that might be holding the data is transferred to a another thank you (URL) page ..

anyways .., right now I'm a bit out of it, I will need to wait till I can better understand the step by step flow of the process and in overall to try and get a better picture of how all this needs to be worked out  ..

Thanks again 

Edit: Thanks again for the example! , finally got it worked out.. Your help saved me from a lot of trouble :sweating: :thumbsup:

 

Edited by Deye
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

×
×
  • Create New...