How does the UpdateAsyncEvents works step by step.

Monkey Forums/Monkey Beginners/How does the UpdateAsyncEvents works step by step.

yiotoo(Posted 2014) [#1]
I am trying to understand how the command UpdateAsyncEvents works.

I went and used the code in: http://www.monkeycoder.co.nz/Community/posts.php?topic=7698

And put some Print like in below:


Class TcpEchoServer Implements IOnAcceptComplete


	Method New(port:Int)
		Print "Class TcpEchoServer - Method New" '<-----------------------------------------------
		_socket=New Socket( "server" )
		If Not _socket.Bind( "",port ) Then
			hasMsg = "Server IP Bind Failed"
			Return
		Else
			hasMsg = "Bind Successful"			
		End If
		_socket.AcceptAsync( Self )
		
	End
	
	Private
	
	Field _socket:Socket
	Field clients:TcpEchoServerClient[10]
	Field onClient:Int = 0
	
	
	Method OnAcceptComplete:Void(socket:Socket, source:Socket)
		Print "Class TcpEchoServer - Method OnAcceptComplete" '<-----------------------------------------------
		If Not socket Then
			hasMsg = "Server Client Connection Accept Error" ' "Accept Error"
			Return 
		End If		
		hasMsg = "TcpEchoServer: Accepted client connection"
		clients[onClient] = New TcpEchoServerClient( socket )
		onClient = onClient + 1
	End
	
	
End

Class TcpEchoServerClient Implements IOnSendComplete,IOnReceiveComplete

	Method New(socket:Socket)
		Print "Class TcpEchoServerClient - Method New" '<-----------------------------------------------
		_socket=socket
		_socket.ReceiveAsync _data,0,_data.Length,Self
	End
	
	Private
	
	Field _socket:Socket
	Field _data:=New DataBuffer( 1024 )
	
	Method OnReceiveComplete:Void( data:DataBuffer,offset:Int,count:Int,source:Socket )
	 	Print "Class TcpEchoServerClient - Method OnReceiveComplete" '<-----------------------------------------------
		If Not count Or killClient = 1 Then
			hasMsg = "TcpEchoServer: Closing client connection"
			_socket.Close()
			killClient = 0
			Return
		Endif
		
		clientStr = data.PeekString( offset,count )
		Local sstr:String[2]
		sstr = clientStr.Split(",")
		If sstr.Length=2 Then
			clientX = Int(Float(sstr[0]))
			clientY = Int(Float(sstr[1]))			
		End If
		msgStr = serverStr+":"+clientStr		
		data.PokeString(0,serverStr)
		_socket.SendAsync data,0,serverStr.Length(),Self ' offset
	End

	Method OnSendComplete:Void(data:DataBuffer, offset:Int, count:Int, source:Socket)
		Print "Class TcpEchoServerClient - Method OnSendComplete" '<-----------------------------------------------
		_socket.ReceiveAsync _data,0,_data.Length,Self
	End
	
End



	Method SendMore:Void()
		
		
		' we send our coords to the server
		Local n:=_data.PokeString( 0, clickX + "," + clickY )
		_socket.SendAsync _data,0,n,Self
		
		
		countnice[0] += 1
		
		Print "Method SendMore" '<-----------------------------------------------
	End
	
	Method OnConnectComplete:Void(connected:Bool, source:Socket)
		countnice[1] += 1
		Print "Method OnConnectComplete" '<-----------------------------------------------
		
	
		If Not connected Then
			hasMsg = "Error Connecting"
			_socket.Close()
			Return
		Else
			SendMore
		End If
		
	End
	
	Method OnSendComplete:Void(data:DataBuffer, offset:Int, count:Int, source:Socket)
	
		
		_socket.ReceiveAsync _data, 0, _data.Length, Self
		
		countnice[2] += 1
		Print "Method OnSendComplete" '<-----------------------------------------------
		
		
	End

	Method OnReceiveComplete:Void(data:DataBuffer, offset:Int, count:Int, source:Socket)
		
	
		' The server always just sends back its coords, attach ours
		serverStr = data.PeekString( offset,count )
		Local sstr:String[2]
		sstr = serverStr.Split(",")
		If sstr.Length=2 Then
			serverX = Int(Float(sstr[0]))
			serverY = Int(Float(sstr[1]))			
		End If
		msgStr = serverStr + ":" + clientStr
		SendMore
		
		countnice[3] += 1
		Print "Method OnReceiveComplete" '<-----------------------------------------------
		
		
	End
	


So, I went changing the window between the server and the client and collecting the Print step by step like the image bellow:

http://postimg.org/image/qg45m1oxp/
And I couldn't figured out how the UpdateAsyncEvents works calling this methods(OnReceiveComplete(server), OnSendComplete(server), OnReceiveComplete(client),OnSendComplete(client), OnConnectComplete(client)). Becouse I am trying to do a server which many clients could log in.

even the souce don't apper to help very much:

Function UpdateAsyncEvents()
	If _current Return
	Local i:=0
	While i<_sources.Length
		_current=_sources.Get(i)
		_current.UpdateAsyncEvents
		If _current i+=1
	Wend
	_current=Null
End



Nobuyuki(Posted 2014) [#2]
UpdateAsyncEvents, if I remember correctly the last time I checked it, goes and polls a number of async tasks on its current stack to see if the thread has completed what it was assigned to do. This polling system tells the tasks to run OnWhateverCompleted() method as part of an implementing interface of the caller. The caller was provided to the task when you started the async process. Without being polled, the main thread has no way of being able to tell your implementing method what the status of the other processes are, and actually, the only status you get to know is that a task has been completed. It's up to you to figure out which task, and how to handle it.


Nobuyuki(Posted 2014) [#3]
I don't have proper flowcharting software, but despite that, here's my super-professional super-detailed attempt to explain what I presume is going on with async stuff:



yiotoo(Posted 2014) [#4]
I Understood, ty , but how do it organize the stack?

the _sources in the code below seems to be the the tasks, but i can't see how the tasks are organized

becouse my objective is to make one server connecting with many clients,
I can't imagine how it will be with many clients with this UpdateAsyncEvents,


Private

Global _sources:=New Stack<IAsyncEventSource>
Global _current:IAsyncEventSource	'for handling removal of current item.

Public

Interface IAsyncEventSource
	Method UpdateAsyncEvents:Void()
End

Function AddAsyncEventSource:Void( source:IAsyncEventSource )
	If _sources.Contains( source ) Error "Async event source is already active"
	_sources.Push source
End

Function RemoveAsyncEventSource:Void( source:IAsyncEventSource )
	If source=_current _current=Null
	_sources.RemoveEach source
End

Function UpdateAsyncEvents()
	If _current Return
	Local i:=0
	While i<_sources.Length
		_current=_sources.Get(i)
		_current.UpdateAsyncEvents
		If _current i+=1
	Wend
	_current=Null
End



I was thinking to put the _socket.ReceiveAsync ,_socket.SendAsync , _socket.Bind and others things in the method OnUpdate, but I am not sure if it will work.
If I can do it, UpdateAsyncEvents seems to be useless.


yiotoo(Posted 2014) [#5]
Real nice dragon!!! :)


Nobuyuki(Posted 2014) [#6]
There is no organization. The stack exists only to poll all of the tasks involved. They come back in the order a task is completed! In reality, the stack's order is the order you called the async tasks (if you called them yourself), but with networking, the remote server can call a task completed event if the thread tells the update poller (UpdateAsyncEvents()) to do so. That stack isn't useful for your purposes, except maybe to count the number of active tasks, so I wouldn't bother with it. Instead, keep your own Map of connections, or something, to update datagrams that you've positively identified to a specific client.

You must put all of your processing code in its own subroutine or in an OnWhatever() type async event. AFAIK, you can only handle one connection per socket, and thus the server app has to map these client connections to a socket somehow; this is how you keep track of the client connected; it comes in as an argument from onComplete.IOnWhateverComplete(). For the client, it's a lot easier; if you're only connected to one server, then the task will come back with data that is relevant to the active connection. In any case, you have to keep track of the connection yourself.


yiotoo(Posted 2014) [#7]
I think i got it. I will try to play more with more sockets!!
thanks ! and nice Vampire Dragon again lol :)


Nobuyuki(Posted 2014) [#8]
haha, thanks. Hope it works out for you :)


yiotoo(Posted 2014) [#9]
I created a array of TcpEchoServer for create many sockets
Field _server:TcpEchoServer[3]


When I call _server[0] runs ok with the client 1
But when I call _server[1] or _server[2] the server only responds the _socket.AcceptAsync( Self ) to the client 1(again). he ignores the client 2 and 3. Do u have any hint?


rIKmAN(Posted 2014) [#10]
Just had to say - cool dragon! :)


nikoniko(Posted 2014) [#11]
yiotoo wrote:
When I call _server[0] runs ok with the client 1
But when I call _server[1] or _server[2] the server only responds the _socket.AcceptAsync( Self ) to the client 1(again). he ignores the client 2 and 3. Do u have any hint?


Only one server socket is binded to one port.

Update: The First Socket.