Jump to content



Photo

Asynchronous sockets UDF


  • Please log in to reply
40 replies to this topic

#1 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 01 May 2007 - 05:54 PM

Hello folks,
well this is my first public contribution to the forums :)

This is a UDF library providing functions for using asynchronous sockets (and async socket transfer).
An asynchronous socket is a socket with which you can listen(), connect(), send() and recv() asynchronously, that is, while the Windows Sockets implementation (Winsock) attempts to complete your action, your program is doing other stuff. When the action is completed (or has afailed) your program is given a notification. In AutoIt3, you GUIRegisterMsg( $iYourMessageID, $sTheFunctionToCall ) and then do whatever you want to (poll the GUI for events, perform calculations etc.) and have the function called when an event that interests you occurs.

///
EDIT: warning: a lot of yada yada follows beyond this!
If you want to see the effect and read some pretty simple and commented sources just go to this post.

///


This is rather simple. Take a look at this:


This is an example server that uses async sockets. It waits for incoming connections and handles them. At the same time, it does usesless bullshit that you can change to useful work like GUI handling or so.
<removed, download from this post>

This is an example client that uses async sockets. It's crazy because it attempts to connect to one place a few times thus establishing a few simultaneous connections. But that's just what we need since my goal is to prove the simplicity of synchronizing socket transfer and program's normal flow whatsoever.
<removed, download from this post>

<Obsolete>
I'm too damn lazy to write a client now... If this gains interest (or I'm at 3A.M. by the computer one night) I'll write one... At present, use one of those blocking TCP clients or use this one. It's a piece of crap, from the days when I was scripting in AutoIt only, and it's not finished. And, oh, it's in lithuanian :D I think you'll understand though. When prompted, enter your local IP address and port to listen to. It starts to listen on that port. There are only two commands (as I said, it's not finished (and I'm not planning to finish it)) you can use:
"prisij hostname_or_IP:port" connects to a host. Use this to test the async server.
"atsij hostname_or_IP:port" disconnects from a host.
Edit: forgot to mention that any other text that is entered is sent to all the connected peers. This way you can see how async server gets notified about received data.
It's an old and crappy server+client (I know it's childish). It uses blocking sockets and shouldn't be used unless you can't find a simple client to test the server...
Attached File  CNCServ.au3   9.71K   900 downloads</Obsolete>

Well basically this is it. Here is the UDF:
Attached File  ASock.au3   5.09K   1780 downloads

OK it's a very long post I have here. If anyone reads it fully, congrats! :D

Anyway, any comments, criticism, ideas and feedback are eagerly waited. If you find this useful or a piece of crap, please let me know.

Cheers
Kostas

EDIT: See my next post to get more info about the _ASock functions.
EDIT #2: this is the same async server that instead of doing nothing while Winsock is polling for data and such, it sends large chunks of data. This version shows that TCPSend() returns immediately even after being requested to send a lot of data if used with async sockets.
Attached File  server_.au3   7.03K   821 downloads
EDIT #3: Posted an example client. It's the same server with some stuff changed.
EDIT #4: Added a really simple server example.

OK I guess that I haven't got the ability to explain easily... :D Yet I hope this will gain interest amongst those that do TCP and socket stuff...

Happy coding! :D

Edited by Jon, 24 July 2009 - 07:24 AM.








#2 BillLuvsU

BillLuvsU

    Useless Member

  • Active Members
  • PipPipPipPipPipPip
  • 1,560 posts

Posted 01 May 2007 - 06:01 PM

Well I'm no expert on sockets and all that other server inter computer thingys but I am able to appreciate the usefullness of this. Very nice!!

Posted Image

Working on the next big thing.Currently Playing: Halo 4, League of LegendsXBL GT: iRememberYhslaw

#3 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 01 May 2007 - 06:08 PM

Thank you fear! :)

Alright I clarified some bits:

Events that shall be used and are tested to perfectly work in AutoIt:

$FD_READ - posted when data has arrived on the socket. I suggest you TCPRecv()'ing only when this occurs.
$FD_WRITE - the conditions to TCPSend() are very good. Nevertheless, use TCPSend() anywhere else.
$FD_ACCEPT - a connection attempt from outside is pending. TCPAccept() it if you want. I suggest you TCPAccept()'ing only when this occurs.
$FD_CLOSE - the remote side has closed the connection / connection lost. Don't forget to TCPCloseSocket() to free the resources used!
$FD_CONNECT - connected to a peer. When you call _ASockConnect(), it returns immediately and almost always (check @extended) is not able to connect/fail that fast, so Winsock posts $FD_CONNECT when the connection is finally made OR an error has occured.
$FD_OOB - UNTESTED You state that you are interested in receiving OOB data. Winsock will announce when such data arrives.

NOTE: check $iError (or whatever you have named it) whether Winsock is telling you about a succeeded event (or one that it hasn't encountered any error on) or a failed event.


These functions have to be used in order to use asynchronous sockets:


Posts a $FD_CONNECT when connected or when afailed.


These functions can be used as usual:

TCPSend() - returns IMMEDIATELY. Attempts to send all the data, no need to check how much is sent.
Returns 0 on closed connection.
Note that $FD_WRITE is posted when it is likely that TCPSend() will succeed very fast / immediately. Nevertheless, call it when you need it.

TCPRecv() - don't call it as usual. Call it when you get a $FD_READ event. This event is posted when data has arrived on the socket.
If you call it on a $FD_READ event and do not receive all the data that has arrived, $FD_READ will be posted again.

TCPAccept() - don't call it as usual. Call it when you get a $FD_ACCEPT event. This event is posted when there is a pending connection to be TCPAccept()'ed.

TCPCloseSocket(), TCPStartup(), TCPShutdown(), TCPNameToIP(), UDFs like SocketToIP() and such.

Edited by Jon, 24 July 2009 - 07:25 AM.
Corrupted code tags


#4 Pascal257

Pascal257

    Prodigy

  • Active Members
  • PipPipPip
  • 158 posts

Posted 01 May 2007 - 07:30 PM

After learning how to use this I'll definitely get this into my programs!!
Thanks for sharing :)

#5 lsakizada

lsakizada

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 392 posts

Posted 01 May 2007 - 08:15 PM

After learning how to use this I'll definitely get this into my programs!!
Thanks for sharing :)



You came up with this after 13 posts?

VERY NICE!
Be Green Now or Never (BGNN)!

#6 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 01 May 2007 - 08:24 PM

Thank you for the warm words mates! :)

You came up with this after 13 posts?
VERY NICE!

Thanks :D Well, I'm not new to AutoIt.. I've been reading the forums occasionaly since maybe Jan '06 or so.. I recall being so happy when I first found out about AutoIt from some batch scripting site :D

#7 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 01 May 2007 - 09:58 PM

An example server and client using asynchronous sockets are now tested to work...
The server does not have to be configured whereas for the client, change the following lines:
Const $IP = "127.0.0.1" Const $PORT = 42775

If you're testing this locally, don't change anything unless you're using a different port.

The server:
Attached File  server.au3   6.58K   1237 downloads
The client:
Attached File  client.au3   5.22K   1203 downloads
You want to follow their ConsoleWrite() output so load them from SciTe or wherever. They'll do some TrayTip()'ing as well.

Read the source code to get the basic understanding of how to use _ASock.au3 (some commentary included) if you don't want to read all the yada yada in the first and the third posts...

Again, please comment on this whether you find this useful or not. Thanks in advance!

OK, I definitely need to go to bed. The school starts in seven hours, and I'm reading random Garfield comics-of-the-day :)

#8 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 02 May 2007 - 12:38 PM

Hmm 118 views and only a couple of responses... :D Geez, are you that lazy to post something? :)

#9 MHz

MHz

    Just simple

  • MVPs
  • 5,400 posts

Posted 02 May 2007 - 01:35 PM

I just spotted your post and read through your rather large, well explained summary and it looks very good. Had no time yet to test or anything but I am taking your word for it, so it is a mighty effort you have done.
Glad to have you as member of the forum and we are grateful for your code that you share with us. :)

#10 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 02 May 2007 - 01:54 PM

Wow thanks man :) I'm glad someone finds it useful...

#11 McGod

McGod

    Formerly Chip

  • Active Members
  • PipPipPipPipPipPip
  • 589 posts

Posted 05 May 2007 - 04:36 AM

This could come very useful! Thanks

#12 BrettF

BrettF

    My Drunk Monkey Guerilla is gonna getcha!

  • MVPs
  • 7,662 posts

Posted 05 May 2007 - 05:38 AM

Good Job zatorg! :) :D :D

#13 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 05 May 2007 - 03:25 PM

Thanks people :)

#14 MHz

MHz

    Just simple

  • MVPs
  • 5,400 posts

Posted 05 May 2007 - 03:29 PM

Thanks people :)

Is there more to come on your project? New idea's, new updates? :D

#15 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 05 May 2007 - 03:42 PM

Is there more to come on your project? New idea's, new updates? :)

Hmm, well, I haven't planned any further development (have stuff to do...) but if there's any interest/need, I can surely happily develop this further... The question is, what to develop? :D ASock.au3 enables you to control async sockets not less than those blocking AutoIt socket functions. If you have any ideas, please let me know.

Maybe I should rewrite the library to be more easily usable? Something like this Manadar's idea?

#16 McGod

McGod

    Formerly Chip

  • Active Members
  • PipPipPipPipPipPip
  • 589 posts

Posted 21 May 2007 - 02:58 AM

Ugh this shit is so confusing, is there any way of making a very simple server? Your example server is too complex.

#17 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 21 May 2007 - 10:09 AM

I second you.. Async stuff ain't simple :) Will try writing one when I have time (and that is today)...

#18 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 21 May 2007 - 01:17 PM

Alrighty here we go... A simple server... Start it, then connect to it with some client and send some data... Then disconnect from it. Notice that you don't have to poll on the sockets in the main While() loop.

AutoIt         
#include <ASock.au3> Const $MYMSG = 1024 ;;; Const $PORT2LISTEN = 42775 ;;; Global $hNotifyGUI = GUICreate( "notify" ) Global $hListen Global $hAccepted = -1 If Not TCPStartup( ) Then Exit 1 If Not _StartServer( "0.0.0.0", $PORT2LISTEN, "OnEvent" ) Then Exit 2 ConsoleWrite( "+> Waiting for connection on port #" & $PORT2LISTEN & "..." & @CRLF ) While $hAccepted = -1; You can alse use a flag like $bConnected which would be changed by OnAccept()                      ; when a connection is accepted...     ; blah blah... WEnd ; Connection accepted! ConsoleWrite( "Connection accepted, socket #" & $hAccepted & @CRLF ) While $hAccepted <> -1; While still connected     ; Do whatever you like here.     ; Do GUI handling etc. WEnd TCPCloseSocket( $hListen ) TCPShutdown( ) Exit 0 ; This is called when an event has happened on a socket. Func OnEvent( $hWnd, $iMsgID, $WParam, $LParam )     Local $hSocket = $WParam; Get the socket involved (either $hListen or $hAccepted in this example)     Local $iError = _HiWord( $LParam ); If error is 0 then the event indicates about a success     Local $iEvent = _LoWord( $LParam ); The event: incoming conn / data received / perfect conditions to send / conn closed         Local $sDataBuff         If $iMsgID = $MYMSG Then; Winsock, not Windows GDI         Switch $iEvent             Case $FD_ACCEPT; Incoming connection!                 If $iError <> 0 Then                     Exit MsgBox( 16, "simpleServer error", "Failed to listen to " & $PORT2LISTEN & "." )                 EndIf                 $hAccepted = TCPAccept( $hListen )             Case $FD_READ; Data has arrived!                 If $iError <> 0 Then                     TCPCloseSocket( $hAccepted )                     $hAccepted = -1                 Else                     $sDataBuff = TCPRecv( $hAccepted, 8192 )                     If @error Then                         TCPCloseSocket( $hAccepted )                         $hAccepted = -1                     Else                         ConsoleWrite( "{{" & $sDataBuff & "}}" & @CRLF )                         TrayTip( "Data has arrived!", $sDataBuff, 30 )                     EndIf                 EndIf             Case $FD_WRITE                 If $iError <> 0 Then                     TCPCloseSocket( $hAccepted )                     $hAccepted = -1                 EndIf             Case $FD_CLOSE; Bye bye                 _ASockShutdown( $hAccepted ); Graceful shutdown.                 Sleep( 1 )                 TCPCloseSocket( $hAccepted )                 $hAccepted = -1         EndSwitch     EndIf EndFunc Func _StartServer( $sIP, $iPort, $sFunc )     $hListen = _ASocket( )     If @error Then Return False     _ASockSelect( $hListen, $hNotifyGUI, $MYMSG, BitOR( $FD_ACCEPT, $FD_READ, $FD_WRITE, $FD_CLOSE ) )     If @error Then Return False     GUIRegisterMsg( $MYMSG, $sFunc )     _ASockListen( $hListen, $sIP, $iPort )     If @error Then Return False     Return True EndFunc


Cheers. Don't hesitate to ask what you don't understand...

Edit: some foolish grammar.
Edit2: slightly edited the script to TCPCloseSocket() properly. Not a bug, but still...

Edited by zatorg, 23 May 2007 - 05:57 AM.


#19 McGod

McGod

    Formerly Chip

  • Active Members
  • PipPipPipPipPipPip
  • 589 posts

Posted 22 May 2007 - 08:28 PM

Works great, you missed a c on EndFunc btw.

#20 zatorg

zatorg

    Wayfarer

  • Active Members
  • Pip
  • 79 posts

Posted 23 May 2007 - 05:50 AM

Great then. And thanks, yeah, I somehow missed it... :)




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users