Jump to content



Photo

Asynchronous sockets UDF


  • Please log in to reply
40 replies to this topic

#21 Ranmaru

Ranmaru

    Wayfarer

  • Active Members
  • Pip
  • 65 posts

Posted 16 November 2007 - 12:20 PM

This is awesome, just what I was looking for, thanks! :P

Edited by Ranmaru, 16 November 2007 - 12:20 PM.

Posted ImagePosted Image







#22 AzKay

AzKay

    MY LOVE FOR YOU IS LIKE A TRUCK, BERSERKERRRRRRR

  • Active Members
  • PipPipPipPipPipPip
  • 1,971 posts

Posted 16 November 2007 - 02:14 PM

Would there be a simpler version for the client?
Like, You wrote a simpler version of the server.
# MY LOVE FOR YOU... IS LIKE A TRUCK- #

#23 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 18 November 2007 - 10:29 AM

Would there be a simpler version for the client?
Like, You wrote a simpler version of the server.

Hey,
ooh, it has been a long time since I last visited these forums...
Let me see. Which part don't you understand? I admit it's a bit confusing with all those new function names etc. Maybe I should comment on what the script does?

#24 AzKay

AzKay

    MY LOVE FOR YOU IS LIKE A TRUCK, BERSERKERRRRRRR

  • Active Members
  • PipPipPipPipPipPip
  • 1,971 posts

Posted 19 November 2007 - 02:11 PM

I just want to use the functions as a simple simple TCP connection, Like, For basic testing purposes.
Like, Connecting to a server, sending data, and receiving the response.
# MY LOVE FOR YOU... IS LIKE A TRUCK- #

#25 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 19 November 2007 - 02:30 PM

Right, will try if I find some time. And that's either NOW or Saturday, cause will be totally N/A all this week.

#26 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 19 November 2007 - 03:16 PM

OK, here's a PoC but it's not tested cause my Windows is going nuts. Will prob switch to OS X Leopard some time soon :P

AutoIt         
#include <ASock.au3> Const $MYMSG = 1024 Global $bConnectResult = 0 Global $hSocket = -1 ;;; Const $IP2CONNECT2   = "127.0.0.1" Const $PORT2CONNECT2 = 42775 ;;; If Not TCPStartup( ) Then Exit 1 _StartConnecting( $IP2CONNECT2, $PORT2CONNECT2, "EventHandler" ) If @extended Then     ConsoleWrite( "+> Connected IMMEDIATELY. You have a darn good connection..." & @CRLF ) Else; Wait for the result of the connection attempt.         Do         Sleep( 100 )     Until $bConnectResult <> 0; $bConnectResult = 0 => connecting // = 1 => connected // = -1 => failed     EndIf If $bConnectResult = -1 Then     ConsoleWrite( "+> FAILED to connect to " & $IP2CONNECT2 & ":" & $PORT2CONNECT2 & "." & @CRLF ) Else     ConsoleWrite( "+> YAY, connected!!! :)" & @CRLF )     TCPSend( $hSocket, "Howdy!" )     ; Will catch any response in "EventHandler". You can, however, TCPRecv() but this will be the usual BLOCKING function.     ; Thus, you shouldn't use TCPRecv() :)         ; Do whatever you desire....     While $bConnectResult = 1         TCPSend( $hSocket, "Fl000d..." )         Sleep( 1000 )     WEnd EndIf TCPCloseSocket( $hSocket ) TCPShutdown( ) Exit 0 Func EventHandler _     ( _         $hWnd, _   ; Equals to $hNotifyGUI (see _StartConnecting())         $iMsgID, _ ; Equals to $MYMSG if it's coming from Winsock         $WParam, _ ; Equals to $hSocket         $LParam _  ; Mixture of an error encountered (if any) and the type of event     )         Local $iError = _HiWord( $LParam ); If $iError = 0 then it means the event indicates a success     Local $iEvent = _LoWord( $LParam ); The event: connected / failed to conenct / data received / perfect conditions to send / conn closed         Local $sDataBuff         If $iMsgID = $MYMSG Then; Winsock, not Windows GDI         Switch $iEvent             Case $FD_CONNECT                 If $iError <> 0 Then                     $bConnectResult = -1; Failed to connect.                 Else                     $bConnectResult = 1; Connected!                 EndIf             Case $FD_WRITE                 If $iError <> 0 Then                     $bConnectResult = -1; Error related to TCPSend(), probably failed sending data.                 EndIf             Case $FD_READ                 If $iError <> 0 Then                     $bConnectResult = -1; Failed while attempting to receive data.                 Else                     ; Data arrived!                     $sDataBuff = TCPRecv( $hSocket, 65536 ); 64K buffer                     ConsoleWrite( "+> " & $IP2CONNECT2 & " says: " & $sDataBuff & @CRLF )                 EndIf             Case $FD_CLOSE                 ConsoleWrite( "+> Connection _gracefully_ closed." & @CRLF )                 $bConnectResult = -1         EndSwitch     EndIf EndFunc Func _StartConnecting( $sIP, $iPort, $sFunc )     Local $hNotifyGUI         $hSocket = _ASocket( )     If @error Then Return False         Local $hNotifyGUI = GUICreate( "notify" )     _ASockSelect( $hSocket, $hNotifyGUI, $MYMSG, BitOR( $FD_READ, $FD_WRITE, $FD_CONNECT, $FD_CLOSE ) )     If @error Then Return False         GUIRegisterMsg( $MYMSG, $sFunc )         _ASockConnect( $hSocket, $sIP, $iPort )     If @extended Then; Have connected IMMEDIATELY, no point in waiting for _ASockConnect() result         SetExtended( 1 )         Return True     EndIf         ; Connection attempt issued.     Return True EndFunc


#27 AzKay

AzKay

    MY LOVE FOR YOU IS LIKE A TRUCK, BERSERKERRRRRRR

  • Active Members
  • PipPipPipPipPipPip
  • 1,971 posts

Posted 19 November 2007 - 03:57 PM

Thanks :3
Ill test it, And work out the kinks x3
# MY LOVE FOR YOU... IS LIKE A TRUCK- #

#28 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 19 November 2007 - 03:59 PM

NP, have fun :P
Good luck

#29 AzKay

AzKay

    MY LOVE FOR YOU IS LIKE A TRUCK, BERSERKERRRRRRR

  • Active Members
  • PipPipPipPipPipPip
  • 1,971 posts

Posted 19 November 2007 - 04:37 PM

Works great :3
Thanks.
# MY LOVE FOR YOU... IS LIKE A TRUCK- #

#30 karman

karman

    Wayfarer

  • Active Members
  • Pip
  • 68 posts

Posted 19 November 2007 - 07:16 PM

wowow works great :P i finished my msn client using this^^ finally i can handle conversations and the msn socket at the same time.. i love you..have a great life

#31 AzKay

AzKay

    MY LOVE FOR YOU IS LIKE A TRUCK, BERSERKERRRRRRR

  • Active Members
  • PipPipPipPipPipPip
  • 1,971 posts

Posted 20 November 2007 - 03:34 PM

wowow works great :P i finished my msn client using this^^ finally i can handle conversations and the msn socket at the same time.. i love you..have a great life

Do tell :3
I tried a few days ago, Couldnt get the damn thing to login xD;;
# MY LOVE FOR YOU... IS LIKE A TRUCK- #

#32 Yorn

Yorn

    Adventurer

  • Active Members
  • PipPip
  • 113 posts

Posted 20 November 2007 - 08:46 PM

Okay, what I'm looking for is a combination of these two. I'm working on it on my own, but I figured I'd see if anyone had any pointers or tips for me.

Basically, I want to listen on a port and run the server, then, when the data comes through, I forward it to another port/IP. Then I wait for certain sequences of data to catch and trigger events in response. My idea is to make a bot, but not a cheating one, I play a GTA roleplaying game and want to create NPCs for questing in the game. You can learn more about the game mod at http://www.sa-mp.com but right now, they don't have NPCs for the RPG mod and if I could create NPCs that would quest, the game would be a blast.

As far as actions go in the game, I'm not as concerned, it's more about interfacing my AI bot in to chat with the user, as well as trigger some "/" commands if the user says certain key phrases.

Edited by Yorn, 20 November 2007 - 08:59 PM.


#33 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 24 November 2007 - 08:02 PM

Hey,
I'm back. I hope I can help you.
It seems what you need to do is to listen on a socket, accept connections, receive data from those connections, connect to remote host(s) and forward them the data received. This is more or less like tunneling.
If you have any specific questions, don't hesitate asking. Good luck!!!

And thanks everyone for the warm comments :P

Edited by zatorg, 24 November 2007 - 08:11 PM.


#34 Yorn

Yorn

    Adventurer

  • Active Members
  • PipPip
  • 113 posts

Posted 28 November 2007 - 08:27 PM

Thanks, but now I'm looking at reading memory addresses instead of trying to do UDP tunneling, the traffic is encrypted anyway. All I really want to know how to do is read where the program is storing the text, so this is not a big deal.

#35 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 28 November 2007 - 08:34 PM

Oh, so this is what you want to do! Alright, good luck then. I suggest you using SoftICE to trace the program flow. It is also possible to search for a particular string etc.

Edited by zatorg, 28 November 2007 - 08:38 PM.


#36 ZoScr

ZoScr

    Seeker

  • Active Members
  • 21 posts

Posted 03 December 2007 - 10:31 PM

zatorg,

Many thanks for your thorough, thoughtful and generous contribution! The UDF is exactly what I was looking for, and fills a key gap in AutoIt's built-in socket functionality.

Thank you!

#37 Paulchen

Paulchen

    Wayfarer

  • Active Members
  • Pip
  • 63 posts

Posted 26 February 2008 - 03:49 AM

I get the following error

D:\Data\Entw\AutoIt\TCPIP\server_.au3 (220) : ==> "long_ptr", "int_ptr" and "short_ptr" DllCall() types have been deprecated. Use "long*", "int*" and "short*" instead.:
Local $aRet = DLLCall("Ws2_32.dll","int","getpeername","int",$SHOCKET, "ptr",DLLStructGetPtr($sockaddr),"int_ptr",DLLStructGetSize($sockaddr))

...
; AutoIt Help -> TCPRecv
Func SocketToIP($SHOCKET)
Local $sockaddr = DLLStructCreate("short;ushort;uint;char[8]")

Local $aRet = DLLCall("Ws2_32.dll","int","getpeername","int",$SHOCKET, _
"ptr",DLLStructGetPtr($sockaddr),"int_ptr",DLLStructGetSize($sockaddr))
If Not @error And $aRet[0] = 0 Then
$aRet = DLLCall("Ws2_32.dll","str","inet_ntoa","int",DLLStructGetData($sockaddr,3))
If Not @error Then $aRet = $aRet[0]
Else
$aRet = "(Could not get the address)"
EndIf

$sockaddr = 0

Return $aRet
EndFunc
....

i have found the following description
http://www.autoitscript.com/forum/index.ph...opic=56168&

can somebody help me to eliminate this?

Attached Files



#38 rover

rover

    unmutual

  • Active Members
  • PipPipPipPipPipPip
  • 825 posts

Posted 26 February 2008 - 05:05 AM

I get the following error

D:\Data\Entw\AutoIt\TCPIP\server_.au3 (220) : ==> "long_ptr", "int_ptr" and "short_ptr" DllCall() types have been deprecated. Use "long*", "int*" and "short*" instead.:
Local $aRet = DLLCall("Ws2_32.dll","int","getpeername","int",$SHOCKET, "ptr",DLLStructGetPtr($sockaddr),"int_ptr",DLLStructGetSize($sockaddr))

just change 'int_ptr' to ptr
server.au3 with asock.au3 works for me
in v3.2.8.1 and v3.2.11.1

from TCPRecv example in help file
; AutoIt Help -> TCPRecv Func SocketToIP($SHOCKET)     Local $sockaddr, $aRet     $sockaddr = DllStructCreate("short;ushort;uint;char[8]")     $aRet = DllCall("Ws2_32.dll", "int", "getpeername", "int", $SHOCKET, _             "ptr", DllStructGetPtr($sockaddr), "ptr", DllStructGetSize($sockaddr))     If Not @error And $aRet[0] = 0 Then         $aRet = DllCall("Ws2_32.dll", "str", "inet_ntoa", "int", DllStructGetData($sockaddr, 3))         If Not @error Then $aRet = $aRet[0]     Else         $aRet = 0     EndIf     $sockaddr = 0     Return $aRet EndFunc   ;==>SocketToIP

I see fascists...

#39 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 29 November 2009 - 05:08 PM

Hi zatorg

Thanks a Ton for posting Asynchronous sockets UDF.I have been looking for this since from last 3 months .
It's working fine for me, both the clients and the server.

I have a doubt, I am having a client server application , where all the clients are connecting to the server .When they establish a connection they can start talk each other.Now it is totally based on TCP/IP. One loop is always monitoring the data's from the connected sockets.If anything comes it will process accordingly.

If i change my server application by using Asynchronous sockets method will i be able to communicate between server and the clients. Because i am having 'n' number of clients.

If possible can u tell me how can i implement the same.I have tried a lot but i am not able to figure out.

Thanks & Regards
Ajomon

Hey Ajomon,

I think that what you are basically looking at is an adaptation of the original example script <server.au3> which accepts multiple connections and then waits for Winsock to notify about events regarding those connections (e.g. in your case, you'd be interested in being notified about (and reading) received data as well as knowing which client in particular sent you that data -- and it's all in that script).
http://www.autoitscript.com/forum/index....le=attach&section=attach&attach_id=14413 (I hope this is reachable by all users; in any case, it's attached in this post: http://www.autoitscript.com/forum/index....?showtopic=45189&view=findpost&p=336722)
I think that the original script will no longer work due to AutoIt language changes (unfortunately, I no longer have AutoIt around), but e.g. rover has addressed one of the issues here.

On a very abstract level, what you need to do is to have an array of sockets (connection identifiers). When you establish all the connections with the clients (see source code of the script), you do whatever you want. Once data from a specific client is received, OnSocketEvent() is called. This line determines which client has sent the data (it is the socket number in your array of sockets):
Local $nSocket = $iMsgID - $WM_USER - 1

In order for this to work, you have to previously inform WinSock that for each socket, you want to receive a specific ID ($iMsgID):
(this is executed when a new connection has been accepted; on each such event, FreeSock() is called which returns the number of an unused element in the array of sockets)
_ASockSelect( $hSockets[ $iFreeSock ], $hNotifyGUI, $WM_USER + $iFreeSock + 1, BitOR( $FD_READ, $FD_WRITE, $FD_CLOSE ) )

_ASockSelect() "registers" the socket in the sense that it tells Winsock to notify the program when certain events that interest us (in this case, receival of data, closure of the connection and perfect conditions to send data to that client (this last one is not that interesting)) take place. Notice the "$WM_USER + $iFreeSock + 1" part: $iFreeSock is the number of an unused element in the socket array ($iFreeSock stores the number returned by FreeSock()); "$WM_USER + 1" is needed because the notification process uses Windows Graphics Device callback mechanism; what this means is that the mechanism might send events unrelated to the socket concerned (it might be about the dummy GUI window needed to receive notifications from Winsock). Starting with a constant "WM_USER" + 1 (WM_USER is the last (biggest) constant still reserved for Winsock-unrelated events), you are free to choose a number that will be received by OnSocketEvent(). In this script, the number is basically the socket's in question position in the array.

Perhaps you can tell why your current implementation (which, as I understand, uses AutoIt's built-in socket functions) does not satisfy you? I gather you want to do more useful stuff (e.g. handle the GUI) rather than just poll for socket events which Winsock can do for you? If so, then maybe you just need to adapt the script <server.au3> - if I'm totally wrong, maybe you can paste relevant excerpts of your code here/somewhere that we can look at.

Edit: oh, sorry, I haven't actually answered your question :) - yes (see server.au3 - the part in OnSocketEvent() where there is a TrayTip displayed telling what and from where was received - you could simply change that line(s) to TCPSend($hSocket, "response data"))

Edit 2: I also forgot to mention that in order to "register" a socket, you also need to GUIRegisterMsg($id_to_use, "FunctionName"):
For $i = 0 To $N_MAXSOCKETS - 1     $hSockets[ $i ] = -1     GUIRegisterMsg( $WM_USER + 1 + $i, "OnSocketEvent" ) Next

In this script, it is done before any actual socket operations (listening etc.) are performed.

Edited by zatorg, 29 November 2009 - 05:19 PM.


#40 Tr4d3r

Tr4d3r

    Seeker

  • New Members
  • 1 posts

Posted 14 February 2010 - 12:07 AM

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




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users