RTMFP, Stratusを試してみた

UDPベースのP2P通信のためのプロトコルRTMFPと、それをサポートするサービス「Stratus」。
Adobe Labs - Stratus

通信部分はきれいに隠蔽されていて、ActionScriptから使いやすくなっています。
勉強がてら、文字列のメッセージを1対1で送受信する簡単なプログラムを書いてみました。

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="creationCompleteHandler(event);">
	<mx:Script>
	<![CDATA[
		import flash.events.NetStatusEvent;
		import flash.net.NetConnection;
		import flash.net.NetStream;
		
		private const URL_CONNECT:String = "[StratusのURL]";
		private const PUBLISH_NAME:String = "rtmfp_test";

		private const STATE_NOT_CONNECT:int = 0;
		private const STATE_CONNECT:int = 1;
		
		[Bindable]
		private var state:int = STATE_NOT_CONNECT;

		private var netConnection:NetConnection = null;
		private var sendStream:NetStream = null;
		private var recvStream:NetStream = null;
		
		private function creationCompleteHandler(event:Event):void {
			netConnection = new NetConnection();
			netConnection.addEventListener(NetStatusEvent.NET_STATUS, netConnectionHandler);
			netConnection.connect(URL_CONNECT);
		}
		
		private function netConnectionHandler(event:NetStatusEvent):void {
			logText.text += "NetConnection event: " + event.info.code + "\n";
			
			switch (event.info.code) {
				case "NetConnection.Connect.Success":
					logText.text += "my ID: " + netConnection.nearID + "\n";
					createSendStream(netConnection.nearID);
					break;
				case "NetConnection.Connect.Closed":
					state = STATE_NOT_CONNECT;
					break;
				case "NetConnection.Connect.Failed":
					state = STATE_NOT_CONNECT;
					break;
				case "NetStream.Connect.Success":
					state = STATE_CONNECT;
					break;
				case "NetStream.Connect.Closed":
					hangUp();
					state = STATE_NOT_CONNECT;
					break;
			}
		}
		
		private function hangUp():void {
			if (recvStream) {
				recvStream.close();
				recvStream.removeEventListener(NetStatusEvent.NET_STATUS, recvStreamHandler);
				recvStream = null;
			}
		}
		
		private function createSendStream(myID:String):void {
			sendStream = new NetStream(netConnection, NetStream.DIRECT_CONNECTIONS);
			sendStream.addEventListener(NetStatusEvent.NET_STATUS, sendStreamHandler);
			sendStream.publish(PUBLISH_NAME);
			var c:Object = new Object;
			c.onPeerConnect = function(caller:NetStream):Boolean {
				logText.text += "onPeerConnect: " + caller.farID + "\n";
				if (!recvStream) {
					createRecvStream(caller.farID);
				}
				return true;
			}
			sendStream.client = c;
		}
		
		private function createRecvStream(farID:String):void {
			recvStream = new NetStream(netConnection, farID);
			recvStream.addEventListener(NetStatusEvent.NET_STATUS, recvStreamHandler);
			recvStream.play(PUBLISH_NAME);
			var o:Object = new Object();
			o.onIm = function(msg:String):Boolean {
				logText.text += msg + "\n";
				return true; 
			}
			recvStream.client = o;		
		}

		private function sendStreamHandler(event:NetStatusEvent):void {
			logText.text += "sendStreamHandler event: " + event.info.code + "\n";
		}
		
		private function recvStreamHandler(event:NetStatusEvent):void {
			logText.text += "recvStreamHandler event: " + event.info.code + "\n";
		}

		private function callButtonClickHandler(event:Event):void {
			createRecvStream(targetUserID.text);
		}
		
		private function sendButtonClickHandler(event:Event):void {
			logText.text += msg.text + "\n";
			sendStream.send("onIm", msg.text);

			msg.text = "";
		}
		
	]]>
	</mx:Script>
	
	<mx:ViewStack selectedIndex="{state}" resizeToContent="true">
		<mx:HBox>
			<mx:Label text="Target ID:"/>
			<mx:TextInput id="targetUserID" width="400" />
			<mx:Button id="callButton" label="call" click="callButtonClickHandler(event);" />
		</mx:HBox>
		<mx:HBox>
			<mx:Label text="Message:"/>
			<mx:TextInput id="msg" width="400"/>
			<mx:Button id="sendButton" label="send" click="sendButtonClickHandler(event);" />
		</mx:HBox>
	</mx:ViewStack>

	<mx:TextInput id="logText" width="500" height="300" />
</mx:Application>

※2/16 AM1:03 切断処理を追加


以下のようにして動作を確認できます。

  1. ブラウザで2つ開く
  2. 一方の「my ID」の値を、もう一方の「Target ID」にコピペして「call」をクリック。これでP2P接続ができる
  3. 一方の「Message」に適当な文字列を入れて「send」をクリックし、文字列メッセージを送信。するともう一方で文字列メッセージを受信する。

パケットロス対策とかパケットの届く順番とかは、どうなっているんだろう。次はそのあたりを調べてみないと。