Jump to content

Asynchronous sockets UDF


zatorg
 Share

Recommended Posts

Hello, excelent piece of code ... i already use it on many proyects ...

But, i have a problem when this is performed by a Service AutoIT application ... the message never are received...

I Can see in the server part that the client connect, but in the client, the event never is fired ... i think is because in the system account, there is not a visible desktop ...

Any idea to make a event RECEIVED running inthe system desktop as a service?

Thanks a lot.

Tr4d3r

I had the same problem. You will either have to change the credentials of the service or somehow change the default restrictions for the SYSTEM account if you need it to be SYSTEM or rather set the service to run as NETWORK SERVICE instead of SYSTEM and it will work then.

Edited by LoWang
Link to comment
Share on other sites

  • 3 years later...
  • Replies 41
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Thank you for this useful UDF.  In addition to async connection, my project has need for an asynchronous version of TCPNameToIP as well.  So I wrote one to contribute to the "ASock" library. 

#include <Memory.au3>
const $MAXGETHOSTSTRUCT = 1024
Func _AllocHostEnt()
    Return _MemGlobalAlloc( $MAXGETHOSTSTRUCT, $GPTR )
EndFunc
Func _FreeHostEnt($ptr)
    _MemGlobalFree($ptr)
EndFunc
Func _WSAAsyncGetHostByName($name, $hWnd, $uiMsg, $ptr)
    If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" )
    Local $iRet = DllCall( _
            $hWs2_32, _
            "int", "WSAAsyncGetHostByName", _
            "hwnd", $hWnd, _
            "uint", $uiMsg, _
            "str", $name, _
            "ptr", $ptr, _
            "int", _MemGlobalSize($ptr) _
            )
    If @error Then
        SetError(1, @error)
        Return False
    EndIf
    If $iRet[ 0 ] = 0 Then
        SetError(2, _WSAGetLastError())
        Return False
    EndIf
    Return True
EndFunc
Func _GetIPFromHostEnt($ptr)
    local $hostent = DllStructCreate("ptr h_name;ptr h_aliases;short h_addrtype;short h_length;ptr h_addr_list", $ptr)
    if @error > 0 Then return ""
    local $listptr = DllStructGetData($hostent, "h_addr_list")
    if $listptr <> 0 Then
        local $firstptr = DllStructGetData(DllStructCreate("ptr", $listptr), 1)
        if $firstptr <> 0 Then
            ; at least one address
            local $inaddr = DllStructCreate("ULONG", $firstptr)
            local $uint = DllStructGetData($inaddr,1)
            If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" )
            local $aRet = DllCall($hWs2_32, "str*", "inet_ntoa", "UINT", $uint)
            if @error > 0 Then Return ""
            Return $aRet[0]
        EndIf
    Else
        SetError(1)
        Return ""
    EndIf
    SetError(2)
    return ""
EndFunc

Notes:

  • Unlike the rest of the library, this operation needs to fill a buffer asynchronously and return it, so the usage is a little more elaborate (as if having WM_USER messages flying around wasn't already crazy enough!).
  • I provide a parsing function because the "hostent" structure requires some digging and parsing to get a string IP address out of it. 
  • Ironically, what I do with this is just pass it back into the _ASockConnect which immediately turns it back into an in_addr ;)  But anyway, rather than changing the Connect API to accept in_addr's I thought it would be more "AutoIt-like" to be able to continue operating with string IPs.
  • Due to a combination of circumstances in my project, I elected to provide real memory alloc/dealloc functionality instead of relying on AutoIt's built-in reference counted DLL struct allocation.  For simple projects that only need to run one of these at a time, you could just DllCreateStruct your own buffer and pass it in, skipping the explicit alloc/deallocs shown.

Usage:

Similar to the rest of the library, this guy operates by kicking off the operation and returning immediately.  Winsock's thread will complete some time later and then send a Windows Message of your choice to the Window handle you specify.

My below example code is a bit contrived for simplicity (I use a static message number and a single buffer).  For simple usage like this, the extra step of memory allocation seems useless. But it becomes important if you have a more complicated program that might have several of these going at once.

local $msg = $WM_USER+1
GUIRegisterMsg($msg, "OnCalledBack")
local $hostent = _AllocHostEnt()
_WSAAsyncGetHostByName($name, $hGUI, $msg, $hostent)

Func OnCalledBack( $hWnd, $iMsgID, $WParam, $LParam )
    ; #define WSAGETASYNCERROR(lParam)            HIWORD(lParam)
    local $iError = _HiWord ($LParam)
    if $iError = 0 then
        local $ip = _GetIPFromHostEnt($hostent)
        ...
    Endif
    _FreeHostEnt($hostent)
EndFunc
Edited by ferrix
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...