P2P Flash On A Local Network Part 1

Flash Player has provided an API for peer-to-peer communication since 10.1 (and in AIR since 2.0). P2P over the Internet requires some server-side technology (such as Flash Media Server) but on a local network it’s really easy; no server stuff and it can be set up in a few lines of code.

Below are two instances of the same swf; anything entered in the input field will be sent to all other instances of the swf and appear in their text areas – feel free to open more copies of this page if you want to increase the number of swfs. I also trace out some basic info to the text area so you can see whats going on behind the scenes.

Flash Player popupYou should get an annoying Flash Player alert asking you to confirm that you are happy to allow p2p for this website before it is activated (sigh):

 

{P2PLanExample1}

 

Update: This example does not work in Chrome browser with PPAPI version of Flash Player. To use, goto chrome://plugins and enable NPAPI version.

And here’s the code (using MinimalComps for the UI):

package
{
	import com.bit101.components.InputText;
	import com.bit101.components.PushButton;
	import com.bit101.components.TextArea;

	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.events.NetStatusEvent;
	import flash.net.GroupSpecifier;
	import flash.net.NetConnection;
	import flash.net.NetGroup;

	[SWF(width="250",height="300",backgroundColor="#EEEEEE")]
	public class P2PLanExample1 extends Sprite
	{
		private var netConn:NetConnection;
		private var group:NetGroup;

		private var inputText:InputText;
		private var outputText:TextArea;
		private var submitButton:PushButton;

		public function P2PLanExample1()
		{
			//create UI (using minimalComps)
			inputText = new InputText(this, 10, 10, "");
			submitButton = new PushButton(this, 120, 10, "Send", btnHandler);
			submitButton.width = 70;
			submitButton.enabled = false;
			outputText = new TextArea(this, 10, 35, "");
			outputText.width = 230;
			outputText.height = 255;

			//setup connection object
			netConn = new NetConnection();
			//listen for result of setup
			netConn.addEventListener(NetStatusEvent.NET_STATUS, netHandler);
			//connect to LAN
			netConn.connect("rtmfp:");
		}

		private function btnHandler(event:MouseEvent):void
		{
			//update UI
			outputText.text += "[SENDING]\n"+inputText.text+"\n";
			// Create an object to hold the data to send
			var obj:Object = new Object();
			//add the data
			obj.txt = inputText.text;
			//add some extra data to ensure every sent object is unique
			obj.id = new Date().time;
			//send to everyone in group
			group.post(obj);
		}

		private function netHandler(event:NetStatusEvent):void
		{
			//update UI
			outputText.text += "[EVENT]\n"+event.info.code+"\n";
			//handle event
			switch(event.info.code)
			{
				//connection succeeded so setup a group
				case "NetConnection.Connect.Success":
					setupGroup();
					break;
				//group setup succeeded so enable submit
				case "NetGroup.Connect.Success":
					submitButton.enabled = true;
					break;
				//posting received so add to output
				case "NetGroup.Posting.Notify":
					outputText.text += "[RECEIVED]\n"+event.info.message.txt+"\n";
					break;
			}
		}

		private function setupGroup():void
		{
			//create a GroupSpecifier object
			var groupspec:GroupSpecifier = new GroupSpecifier("myGroup");
			//enable posting (to entire group)
			groupspec.postingEnabled = true;
			//allow data to be exchanged on IP multicast sockets
			groupspec.ipMulticastMemberUpdatesEnabled = true;
			//set the IP adress and port to use
			groupspec.addIPMulticastAddress("225.225.0.1:30000");
			//create NetGroup with our NetConnection using GroupSpecifier details
			group = new NetGroup(netConn, groupspec.groupspecWithAuthorizations());
			//listen for result of setup
			group.addEventListener(NetStatusEvent.NET_STATUS, netHandler);
		}

	}
}

Setting Up

In the constructor i create the UI and then set up a NetConnection object. By passing only the protocol when calling connect (netConn.connect("rtmfp:");), we are telling FP that we want a local network connection. RTMFP stands for Real Time Media Flow Protocol btw.

If this was an internet-wide p2p setup, we would use something like netConn.connect("rtmfp://myServer.com/myPath"); to connect to a remote server (which helps set up the p2p connections – you wouldn’t want to connect to every flash player connected to the Internet would you?).

Once the NetConnection succeeds (or fails), a NetStatusEvent.NET_STATUS event is fired – which is picked up by the netHandler method. The info.code property of the NetStatusEvent can be used to determine what happened – in this case we are hoping for “NetConnection.Connect.Success” (and not “NetConnection.Connect.Failed”; a full list of possible codes is available at http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/NetStatusEvent.html).

Once the NetConnection object is ready, we set up a NetGroup in the setupGroup() method. First, we create a GroupSpecifier object and set some properties – giving the group a name of “myGroup” (you can have multiple groups), enabling posting to all members of the group, telling the group to use IP sockets and finally stating the IP address and port to utilise – 225.225.0.1:30000 is the value used in the AS3 docs and it works for me, so i suggest leaving it as it is unless you feel a need to change it.

Lastly, we create the NetGroup object, passing in a reference to the NetConnection and utilising a GroupSpecifier helper method to pass the groupspec data.

Success (or failure) of the NetGroup initialisation will be signalled by another NetStatusEvent.NET_STATUS event – this time with a code of “NetGroup.Connect.Success”. Once the NetGroup is ready, p2p communication is good to go.

Send And Receive

Sending data is managed here by the btnHandler method; we simply create an Object, attach some data to it (in this case, the text from the input field), and pass the object to the NetGroup post method. That’s it.

Incoming data (sent from the post method) fires a NetStatusEvent.NET_STATUS event with a code of “NetGroup.Posting.Notify”. The info.message property of the event is the same Object that was sent with the post method, so for this example (in netHandler method) the text data is in event.info.message.txt. Here we just add it to the output text area.

Final Thoughts

There can be a noticable lag between sending and receiving when the NetGroup is first initialised, but this usually improves greatly after a few messages have been sent.

Also, i should make clear that the swfs don’t need to be on the same device – it really is the whole local network – so if your phone hooks ups to your wifi when you’re at home, a swf in your browser could communicate with an AIR app running on your phone (use your phone as a remote control for a game running in the browser for example).

In part 2, i will extend this example to display info about members of the group and configure message sending to specific users. Until then, here’s the source code: https://github.com/LeeBurrows/blog-source-code

/* UPDATE */

It turns out that every message object sent must be completely unique or it may get ignored (ie: mistaken for a previous message already received). For instance, sending “hello” twice, may result in only a single “hello” being received.

Luckily, we can easily cover this by adding a unique property to each message object to ensure no two are ever alike. I have amended the btnHandler method to include a time stamp on each message object. Job done.

//add some extra data to ensure every sent object is unique
obj.id = new Date().time;

19 thoughts on “P2P Flash On A Local Network Part 1

  1. AS3DEV

    It seems as though peer-to-peer over a local network no longer works. This example and others are not able to send text back and fourth. I have tried on various networks, computers, and browsers. I am thinking it might be broken in Flash Player 11?

    Reply
    1. Lee Post author

      hi AS3DEV

      i am using FP 11 and it works for me.

      are you getting the player settings popup asking for permission to use p2p?

      you can see which sites you have allowed or blocked by right-clicking on a swf and selecting ‘Global Settings…’. In the ‘playback’ tab, check that ‘Ask me when a site wants to use peer-assisted networking’ is selected and click on ‘Peer-assisted Networking Settings by Site…’ to see settings for individual sites.

      Reply
  2. AS3DEV

    @Lee

    Thanks for the quick reply. I did allow peer assisted networking. P2P in Flash has worked for me in the past, but it doesn’t now. Weird, well at least I know it is not FP 11. Right now it only works for me with 2 different browsers or tabs on the same computer.

    Reply
  3. alfonso

    very nice!
    I’m using this technique for syncing sounds from various devices in order to make music: the app is called fireTheDj and it’s avaiable at the android market.
    I see lots of possibilities with this feature!
    regards
    alfonsofonso

    Reply
  4. Lee Post author

    @Hangs
    The source code for this is available in part 2 of this tutorial; but if you’re a “newbie” you may want to start with something a little more straight-forward. Adobe’s website has plenty of tutorials to get you going.

    Reply
  5. Gio

    Hi Lee,
    I’ve encountered the same problem, no way to comunicate between two different machine under the same network ( 1 iMac, 1 PC windows 7 ).
    The firewall is disabled on both machine, the permission to use the p2p is set…
    Do you have any hint to solve this situation?
    Bytheway, thanks a lot for the tutorial!

    Reply
  6. Gio

    Hello again,
    probably I understand the nature of the problem, is a router issue.
    At this link http://cc.rtmfp.net/ can find a connectivity checker for the RTMFP, I have several red light…. so I guess that is the problem.

    Reply
    1. Ramy A.

      Hi Gio,

      I’m facing an issue & need some help please, i’ve done 2 android apps that communicate on the local network using then ‘NetConnection’, the second app act like a cursor (trackpad) for the first app, all works good but i’m facing a problem sometimes it disconnect (after 15 or 20 min.) & no data can be send & received between the apps, what do you think is the problem, is it related to a high traffic on the router that could interrupt the NetConnection?
      is there a handler to check if the connection is still working i can use?

      Thx

      Reply
  7. Pingback: LocalConnection - Browser SWF zu AIR Desktop - Flashforum

  8. Nicholas

    Just needed to say, thank you!!

    I could not get my NetGroup.Posting.Notify event to fire no matter what I tried, and after going through your code line by line against mine, it seems that I needed to enable groupSpec.ipMulticastMemberUpdatesEnabled.

    All works perfectly now. I have no idea what exactly that allows or does not allow, or what the MulticastAddress is and what it should always be, but I’ll definitely look into it now, and try to figure out what it’s for.

    Thanks again!!
    Happy New Year!!

    Reply
  9. Pingback: AS3 P2P Chat Client | NNGAFOOK.com | Blog

  10. george

    I have created a simple multicast player using actinscript 3 which works fine and plays multicast stream well . Although even when stream should fail Or even if I stop Flash Media server it returns success codes : “NetConnection.Connect.Success” ,”NetStream.Connect.Success” and “NetStream.Play.Start” . I cant detect it when multicast stream fails in flash player. I need to switch to unicast stream if multicast fails and I cant detect a failure because of wrong status.

    Why I am getting wrong status ?

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>