kkAyatakaのメモ帳。

誰かの役に立つかもしれない備忘録。

AIR.DatagramSocketでBroadcast

ローカルネット内のPCを調べるにはbroadcastを使えばよかろう。
ってことで、DatagramSocketでBroadcastのテスト。


まずは、DatagramSocketの待ち受け。

datagramSocket = new DatagramSocket();
datagramSocket.bind( 50000 );
datagramSocket.receive();
datagramSocket.addEventListener(DatagramSocketDataEvent.DATA, datagramSocket_dataHandler);

特定のポートにbindして、receiveを呼び出せば良い。
あとは通信があれば、イベントが呼ばれる。


んで、メッセージのbroadcast。

var data:ByteArray = new ByteArray();
data.writeUTF( MSG_SEARCH_NODE_BROADCAST );
datagramSocket.send(data, 0, 0, "192.168.0.255", 50000);

ByteArrayしか受け付けないので、生成して渡す。
ローカルネット内で十分なので、アドレスは「192.168.0.255」にする。
datagramSocketは待ち受け用にreceiveしているものを使いまわしても問題ないみたい。


注意が必要なのは、AIR 2 SDK beta2のLinux版ではbroadcastができないこと。
broadcastアドレスにsendすると例外が発生する。
ドキュメントにも非サポートと書いてあるので、まだ未完成なんでしょ。


Linuxメインで書いてたので、また、無駄にハマったよ・・・
実現しているものもあるので、おかしぃなぁと四苦八苦してたんですが、
こんなオチでした。


メッセージの受信はいつも通りイベント。

private function datagramSocket_dataHandler(event:DatagramSocketDataEvent):void
{
	var msg:String = event.data.readUTF();
	trace( "datagram socket data:" + msg + "(" + event.srcAddress + ")" );
	
	if( msg == MSG_SEARCH_NODE_BROADCAST ) {
		//
		var data:ByteArray = new ByteArray();
		data.writeUTF( MSG_NODE_NOTIFICATION );
		//
		var datagramSocket:DatagramSocket = event.target as DatagramSocket;
		datagramSocket.send(data, 0, data.length, event.srcAddress, 50000);
	}
}

Broadcastのメッセージだったら、返信を返す。
自身の情報としてIPアドレスなんかを返せばいいけど、
これはeventオブジェクトから取得できるので、メッセージにはのせなくてOK。
今のとこドキュメントには書いてないけど、eventオブジェクトからdatagramSocketが確保できたので、
こいつを使って返信する。


datagramSocketをメンバでもつ意味が少ないけど、
receiveしているdatagramSocketはアプリ側で持っておかないと、ちゃんと動かない。
まあ、ちゃんと閉じるためにも持っとけばいいか。

Broadcastテスト用の全ソース

今回は構造がシンプルなので、ソースは1個です。

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
	initialize="initializeLogic()" close="closeLogic()">
	
	<mx:Script>
		<![CDATA[

		private function initializeLogic():void
		{
			//
			try {
				datagramSocket = new DatagramSocket();
				datagramSocket.bind( 50000 );
				datagramSocket.receive();
				datagramSocket.addEventListener(DatagramSocketDataEvent.DATA, datagramSocket_dataHandler);
				
				//
				var data:ByteArray = new ByteArray();
				data.writeUTF( MSG_SEARCH_NODE_BROADCAST );
				datagramSocket.send(data, 0, 0, "192.168.0.255", 50000);
			}
			catch( e:Error ) {
				trace( e.message + ":" + e.name );
			}
		}
		
		private function closeLogic():void
		{
			if( datagramSocket ) {
				datagramSocket.close();
			}
		}
		
		private function datagramSocket_dataHandler(event:DatagramSocketDataEvent):void
		{
			var msg:String = event.data.readUTF();
			trace( "datagram socket data:" + msg + "(" + event.srcAddress + ")" );
			
			if( msg == MSG_SEARCH_NODE_BROADCAST ) {
				//
				var data:ByteArray = new ByteArray();
				data.writeUTF( MSG_NODE_NOTIFICATION );
				//
				var datagramSocket:DatagramSocket = event.target as DatagramSocket;
				datagramSocket.send(data, 0, data.length, event.srcAddress, 50000);
			}
		}
		
		static private const MSG_SEARCH_NODE_BROADCAST:String = "message search node broadcast";
		static private const MSG_NODE_NOTIFICATION:String = "message node notification";
		
		private var datagramSocket:DatagramSocket;

		]]>
	</mx:Script>
	
</mx:WindowedApplication>