UdpClient.ReceiveAsync Method

Using (or providing) Microsoft.NET Classes

UdpClient.ReceiveAsync Method

Postby Tomas Gustafsson on Sun Mar 10, 2013 10:21 pm

Hey guys! Now i'd really need some help!

Here is what i am about to use:
http://msdn.microsoft.com/en-us/library/system.net.sockets.udpclient.aspx

I need to transport data packets between simulator applications (see http://www.stormwind.fi). The problem is the NAT that practically every router has these days. The router has one public IP address and distributes it to multiple computers in the local WLAN. All good, but you cannot initiate a peer2peer conversation to another NAT'ed computer on the internet, because there is no way to get the initial conversation up and running, the routers will block (except when using hole punching + a handshaking server, or NATUPnP, or openning tunnels in the router manually).

I intend to use Teredo:
http://technet.microsoft.com/en-us/library/bb457011.aspx

It fakes behind-router-IP4 addresses into IP6 ones, meaning that my one specific computer behind my NAT will be accessible from a IP6 client out on the public net. Hence i can open a connection to another computer that does the same. The IP6 is actually not highly relevant here, the important thing is that there are public Teredo servers.

Eg: A connects to Terede-server, tells it's IP (the router's one) and port (NAT'ed by router). B does the same. Teredo tells both A and B opposite parties info. A and B connect to each other (ie. when A connects to B, A "opens" for incoming from B - and vice versa, so after 1 router blocking, the comm will be opened).

Now, the .net 4.5 "UdpClient" has all that is needed, including a "AllowNATTraversal" property (that's why APL sockets won't do). This does some good housekeeping, and the UdpClient is in good cooperation with Windows firewall.

So now my confusion is: How on earth to use the UdpClient.ReceiveAsync Method? It takes me deep in to .net multithreading, tasks, oddities, strange C#, VB.NET, C++ notation.

A code sample would be highly useful! And urrrgently needed! :-)

Thanks / Tomas
Tomas Gustafsson
 
Posts: 91
Joined: Mon Sep 19, 2011 6:43 pm

Re: UdpClient.ReceiveAsync Method

Postby Tomas Gustafsson on Mon Mar 11, 2013 1:59 am

Re-reading all 100 tabs currently open in Firefox, ... :-)

I found the method BeginReceive for the UdpClient object. It should do the job, but i leave the original question above as is, for the sake of an important topic.

It advances slowly, though. Took me 2 hours to figure out how to construct an IP address in .net. It (status window) just claimed it wants a Byte[] type of data, but i am totally unable to figure out how to construct a Byte[] in .net, from APL. This is highly frustrating - searched through all APL sample workspaces, but nowhere is that mentioned.

Then, eventually a momment ago, i found that

Net.IPAddress.New 192 168 1 1

actually works. Nowhere is said that 4 integers will do as a Byte array (or is it the alternative, Int64? 4 APL integers become a .net Int64???)...

So my request for more .net sample code stands. :-)

Discovered earlier, by desperate trial and error, that []OR fn is to be passed to various .net callbacking functions. Still a question is:

Q: When UdpSocket.BeginReceive gets a UDP packet, it terminates and invokes my call←AsyncCallback.New ⎕OR'foo' - when will that happen? Yes, a short while after the packet came in, but when?

- Any time, while potentially APL executes other code?
- When i call Application.DoEvents from within the game loop?
- Something else required to grab out foo?

Q: Will foo be started sync:ly or async:ly?

I tried call←AsyncCallback.New ⎕OR'foo&' - no go

Q: How DO i make foo execute asynchronously? Call a foo2&[foo's packet data etc] from within foo?

BeginReceive terminates when it gets a UDP packet, so foo must call BeginReceive again. Maybe as first action. Potentially, i can get new UDP data which again calls foo, while foo is still executing. Or can i?
Tomas Gustafsson
 
Posts: 91
Joined: Mon Sep 19, 2011 6:43 pm

Re: UdpClient.ReceiveAsync Method

Postby JohnD|Dyalog on Mon Mar 11, 2013 12:44 pm

Hi Thomas,

OK, lets see if I can answer the questions in the order they were asked

So now my confusion is: How on earth to use the UdpClient.ReceiveAsync Method?

OK, ReceiveAsync returns an instance of a generic "Task" class (see http://msdn.microsoft.com/en-us/library/dd321424.aspx). In C# you could use the "await" keyword to handle the result of this. However, in Dyalog (and I've not tried this), you can either call the "Result" accessor which will block until the result is available, or query the IsCompleted member, and when that returns true, query the result.

Net.IPAddress.New 192 168 1 1

Here the .New syntax determining that the 4 values you have specified will "fit" into an array of bytes and so is calling that overload of the constructor.

Yes, the quadOR of a function can be passed where a delegate would be expected. You can also pass just the name of the function, but the quadOR option exists to prevent any possible overload resolution problems.

When UdpSocket.BeginReceive gets a UDP packet, it terminates and invokes my call←AsyncCallback.New ⎕OR'foo' ... but when?
foo will be called (in a different APL thread) the next time the interpreter checks the .Net interface for pending calls. This pretty much means whenever the interpreter is idle, or when it would check for APL thread switches.

Will foo be started sync:ly or async:ly?
See above. foo will be started in a new APL thread. (In fact Dyalog maintains a map of APL threads to "real" threads so that any call made on a specific "real" thread will always be run on the same APL thread)

Potentially, i can get new UDP data which again calls foo, while foo is still executing. Or can i?
That's an interesting question, and one a cannot answer. I'd suggest that you call BeginReceive again as the LAST action in the callback - just in case.

Best Regards,
John Daintree
User avatar
JohnD|Dyalog
 
Posts: 68
Joined: Wed Oct 01, 2008 9:35 am

Re: UdpClient.ReceiveAsync Method

Postby Tomas Gustafsson on Mon Mar 11, 2013 2:45 pm

John, thank you! That clarifies a lot, and i'm now into implementing.

About this:

I'd suggest that you call BeginReceive again as the LAST action in the callback - just in case.


What would you guess, is there a risk of losing packets while foo executes and the UdpClient has no pending BeginReceive (ie. re-calling BeginReceive at last line of foo, instead of at first)? The alternative would be that UdpClient, while still existing and in some kind of state, collects and accumulates whatever comes in.

What would the APL notation be for creating Byte[]? Very much needed in:

[HostProtectionAttribute(SecurityAction.LinkDemand, ExternalThreading = true)]
public Task<int> SendAsync(
byte[] datagram,
int bytes
)

And the "[HostProtectionAttribute(SecurityAction.LinkDemand, ExternalThreading = true)]" <- has any relevance?
Tomas Gustafsson
 
Posts: 91
Joined: Mon Sep 19, 2011 6:43 pm


Return to Microsoft.NET

Who is online

Users browsing this forum: No registered users and 1 guest