Home  >  

Using UDP socket connections for low-latency and loss-tolerant scenarios in AIR 2 (Part 2)

Author photo
November 18, 2009 | | Comments (9)
AddThis Social Bookmark Button

So now that we understand the usage of UDP lets jump right into building a basic UDP client and server. We'll use the DatagramSocket class to send packets to a specific port at a specific address. We'll also bind our socket to a local port to receive any incoming packets directed at us. In this case we'll be sending packets from an AIR 2 client to a Java server and back over localhost (remote addresses work just the same). Our client application will initiate the communication by saying "Hello, how are you?". Our server will then respond by saying "I'm quite well, thank you".

A quick note about socket security. When dealing with socket connections outside of the application sandbox a cross-domain policy is required. We'll be working inside the application sandbox where we don't have the same constraints, but be aware that some additional work is required when working with other sockets types outside of AIR.

In our AIR application the first thing we want to do is make a new datagramSocket and bind it to an address and a port to receive packets.

 
private var datagramSocket:DatagramSocket = new DatagramSocket();
			
protected function creationCompleteHandler(event:FlexEvent) : void {
 				
       datagramSocket.bind(4455, "127.0.0.1");
 				
}

By doing this we're binding the socket to port 4455 on 127.0.0.1 (localhost). You'll want to make sure that the port isn't already in use by another application or an else error will occur. For our example I've chosen the arbitrary ports "4455" and "4456" for our client and server to communicate back and forth on. Since client and server are both on the same machine we need to use different port numbers but these numbers can be identical when dealing with two remote systems if you'd like.

At this point we're almost ready to receive any data sent to our application on this port. There is one additional step: to enable on the receiving of data using DatagramSocket.receive(). We want to enable this a little further down the line, so for now lets access the payload. The incoming packet comes in the form of a ByteArray and is accessed through the DatagramSocketDataEvent.DATA event.

 
datagramSocket.addEventListener(DatagramSocketDataEvent.DATA, dataHandler)

You'll also want to add handling for I/O and Security errors in case something goes wrong. This works the same as it does for the Socket and XMLSocket classes.

 
private var datagramSocket:DatagramSocket = new DatagramSocket();
			
protected function creationCompleteHandler(event:FlexEvent) : void {
 				
       datagramSocket.addEventListener(DatagramSocketDataEvent.DATA, dataHandler)
 
       datagramSocket.addEventListener(IOErrorEvent.IO_ERROR, IOErrorHandler);
       datagramSocket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
 				
       datagramSocket.bind(4455, "127.0.0.1");
 				
}

Naturally once the data comes in we want to do something with it. How you process your data will depend on the data you are sending. In this case we're expecting a UTF-8 encoded string from the server so we can use the ByteArray.readUTFBytes() method to convert our packet to a string and trace its value

 
private function dataHandler(event:DatagramSocketDataEvent) : void {
 				
       trace( event.data.readUTFBytes(event.data.length) );
 				
}

Now that we're ready to receive data lets send some in order to generate a response. First we'll create a packet (aka, a ByteArray) and write some data into it.

 
var packet:ByteArray = new ByteArray();
 packet.writeUTFBytes("Hello, how are you?");

Now we can send this packet using the datagramSocket.send() method. You'll need to specify the desired address and port as well. Lets send this packet to port "4455" on address "127.0.0.1".

 

protected function clickHandler(event:MouseEvent) : void {
 
       var packet:ByteArray = new ByteArray();
       packet.writeUTFBytes("Hello, how are you?");
 				
       datagramSocket.send(packet, 0, 0, "127.0.0.1", 4455);
 
       datagramSocket.receive() 
 
}

Now that we've sent a packet and we're expecting a response we want to allow that response to be received. You'll notice that datagramSocket.receive() is called immediately after sending our packet so this can happen. Once the response is received and processed its generally best to close the connection unless dealing with a constant stream of data. This can be done using the DatagramSocket.close() method. Once we have our response we're not expecting any more packets so lets close the connection in our data handler.

 
private function dataHandler(event:DatagramSocketDataEvent) : void {
 				
       trace( event.data.readUTFBytes(event.data.length) );
       datagramSocket.close();				
}

And with that we're set to send and receive data on our UDP socket. In part 3 we'll cover how to write our Java UDP socket server for our client to communicate with

Download client and server source

See part 1 of this series here See part 3 of this series here

Read more from Ian McLean. Ian McLean's Atom feed ianmclean on Twitter

Comments

9 Comments

Andrew said:

Hi,

Could you describe how should we configure our envirnoment ?

Thanks,
Andrew

Ian McLean said:

Can you be more specific? The environment for what?

Andrew said:

Well sorry, the question was how to set up an envirnoment for building your examples (flex+java). I was trying to configure FlashDevelop but finally I managed with Flash Builder 4.

So for those who would have similar problems like me here are some small instructions:

I have downloaded latest flex_sdk_4 build (currently it is http://fpdownload.adobe.com/pub/flex/sdk/builds/flex4/flex_sdk_4.0.0.11921.zip) then downloaded latest AIR 2 SDK (http://download.macromedia.com/pub/labs/air/2/b1/air2_b1_sdk_win_111709.zip) and extracted it to the directory of flex_sdk_4 then in Flash Builder 4 go to Window>Preferences, Installed Flex SDKs and give a path to the new SDK. That's it.

For java sources I simply imported them as a new project in Eclipse. and built as a application.

How will be usefull.

Russ said:

Just curious if we could use AIR's datagramsocket class and use it with a flex client instead of air's. Id rather avoid having something someone would have to download.

James Kingsley said:

How would I go about setting up the cross-domain policy?

Tobee said:

Hi,

I pasted my code at http://www.pasteyourcode.com/14552 - the problem is, that my DatagramSocket doesn't receive any data.

Thanks for you help, Tobee

Anonymous said:

Just curious if we could use AIR's datagramsocket class and use it with a flex client instead of air's. Id rather avoid having something someone would have to download.

Mike (Online Measurement Conversions)

Mike said:

Just curious if we could use AIR's datagramsocket class and use it with a flex client instead of air's. Id rather avoid having something someone would have to download.

Mike (Online Measurement Conversions)

Ian McLean said:

Unfortunately no. DatagramSocket is AIR 2 only. There are other socket classes available outside of AIR however if UDP isn't a necessity.

Leave a comment


Tag Cloud

iPad

What's your take on the iPad? (Putting aside the Flash/iPad flame war)

Answer

Latest Features

Recommended for You

@InsideRIA on Twitter

Archives

  • Or, visit our complete archive.  

About This Site

Welcome to the premiere community site for all things RIA sponsored by O'Reilly Media and Adobe Systems Incorporated.