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.
You 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}
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: P2PLanExamples1.zip
/* 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;
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?
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.
@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.
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