Adobe AIR で UDP Socket(DatagramSocket)
以前 ARDrone を Flash(AIR) で飛ばして遊んでるときに使用していた DatagramSocket。
これ、実案件では年に一回使うか使わないかだったりして、必要な時はいろいろ忘れているので…自分用メモ。
・ドキュメントクラス
package { import com.bit101.components.InputText; import com.bit101.components.Label; import com.bit101.components.PushButton; import com.bit101.components.TextArea; import flash.desktop.NativeApplication; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.net.DatagramSocket; import utils.InterfaceUtil; [SWF( width = '330', height = '250', frameRate = '30', backgroundColor = '0xFFFFFF' )] /** * * @author mousepancyo */ public class UDPSocketEx extends Sprite { private var datagramSocket:DatagramSocket; private var _msg:TextArea; private var _targetInput:InputText private var _msgInput:InputText; private var _btSend:PushButton; private var _udpSocket:UDPSocketControler; public function UDPSocketEx() { setup(); NativeApplication.nativeApplication.addEventListener( Event.EXITING, exit ); _msg.text = "Bindable Addresses: \n" + InterfaceUtil.getBindableAddresses().toString(); } private function setup():void { _udpSocket = new UDPSocketControler( InterfaceUtil.getBindableAddresses()); _udpSocket.addEventListener( "receved", onDataReceived ); _udpSocket.setup(); _msg = new TextArea( this, 10, 80 ); _msg.width = 310; var lab1:Label = new Label( this, 10, 201, "Target IP" ); _targetInput = new InputText( this, 60, 201, _udpSocket.localIP ); var lab2:Label = new Label( this, 10, 221, "Input Msg" ); _msgInput = new InputText( this, 60, 221 ); _msgInput.width = 150; _btSend = new PushButton( this, 220, 220, "Send Message", sendMsg ); _msgInput.enabled = _targetInput.enabled = _btSend.enabled = false; var btConnect:PushButton = new PushButton( this, 60, 50, "Connect", onConnect ); var btDisConnect:PushButton = new PushButton( this, 220, 10, "Dis Connect", onDisConnect ); btDisConnect.enabled = false; var lab3:Label = new Label( this, 10, 11, "My IP" ); var localInput:InputText = new InputText( this, 60, 11, _udpSocket.localIP ); var lab4:Label = new Label( this, 10, 31, "Port No" ); var portInput:InputText = new InputText( this, 60, 31, "55555" ); function onConnect( e:MouseEvent ):void { btConnect.removeEventListener( MouseEvent.CLICK, onConnect ); btConnect.enabled = localInput.enabled = portInput.enabled = false; _msgInput.enabled = _targetInput.enabled = _btSend.enabled = btDisConnect.enabled = true; //socketSetup(); _udpSocket.connect( int( portInput.text )); _msg.text = _udpSocket.msg; btDisConnect.addEventListener( MouseEvent.CLICK, onDisConnect ); } function onDisConnect( e:MouseEvent ):void { btDisConnect.removeEventListener( MouseEvent.CLICK, onDisConnect ); btConnect.enabled = localInput.enabled = portInput.enabled = true; _msgInput.enabled = _targetInput.enabled = _btSend.enabled = btDisConnect.enabled = false; _udpSocket.disConnect(); _msg.text = _udpSocket.msg; btConnect.addEventListener( MouseEvent.CLICK, onConnect ); } } private function onDataReceived( e:Event ):void { _msg.text = _udpSocket.msg + "\n" + _msg.text; } private function sendMsg( e:MouseEvent ):void { var ip:String = _targetInput.text; var msg:String = _msgInput.text; _udpSocket.send( ip, msg ); } private function exit( e:Event ):void { _udpSocket.disConnect(); } } }
・UDP接続用のクラス
package { import flash.events.DatagramSocketDataEvent; import flash.events.Event; import flash.events.EventDispatcher; import flash.events.IEventDispatcher; import flash.net.DatagramSocket; import flash.utils.ByteArray; /** * * @author mousepancyo */ public class UDPSocketControler extends EventDispatcher { private var datagramSocket:DatagramSocket; private var _bindAdress:Array; public var msg:String; // My IPAdress private var _localIP:String; // Target IPAdress private var _targetIP:String; // Port Number private var _port:int; /** * Getter */ public function get localIP():String { return _localIP; } public function get targetIP():String { return _targetIP; } /** * Constractor */ public function UDPSocketControler( bindAdress:Array, target:IEventDispatcher = null ) { super( target ); _bindAdress = bindAdress; } public function setup():void { _localIP = _bindAdress[ 0 ]; if ( _localIP.substr( 0, 3 ) == "127" ) { _localIP = _bindAdress[ 1 ]; } } /** * UDP Connect */ public function connect( port:int ):void { _port = port; datagramSocket = new DatagramSocket(); if ( datagramSocket.bound ) { datagramSocket.close(); } datagramSocket.addEventListener( DatagramSocketDataEvent.DATA, onReceved ); // Bind the socket datagramSocket.bind( _port, _localIP ); // Listener datagramSocket.receive(); msg = "Bound to: " + localIP + ":" + _port; } /** * DisConnect */ public function disConnect():void { try { datagramSocket.close(); msg = "datagramsocket closed."; } catch ( e:Error ) { msg = e.message; } } /** * Send */ public function send( ip:String, msg:String ):void { // message in ByteArray var data:ByteArray = new ByteArray(); data.writeUTFBytes( msg ); // Send msg datagramSocket.send( data, 0, 0, ip, _port ); } // Recever private function onReceved( e:DatagramSocketDataEvent ):void { msg = "Received from IP: " + e.srcAddress + " Port: " + e.srcPort + "\n> " + e.data.readUTFBytes( e.data.bytesAvailable ); dispatchEvent( new Event( "receved" )); } } }
・InterfaceUtil クラス
package utils { import flash.net.IPVersion; import flash.net.InterfaceAddress; import flash.net.NetworkInfo; import flash.net.NetworkInterface; public class InterfaceUtil { private static var bindableAddressesCache:Array; public static function getBindableAddresses():Array { if (bindableAddressesCache) return bindableAddressesCache; var addresses:Array = new Array(); var netinfo:NetworkInfo = NetworkInfo.networkInfo; var netifs:Vector.<NetworkInterface> = netinfo.findInterfaces(); for each (var netif:NetworkInterface in netifs) { for each (var addr:InterfaceAddress in netif.addresses) { if (addr.ipVersion == IPVersion.IPV4) { addresses.push(addr.address); } } } bindableAddressesCache = addresses; return addresses; } } }
動作確認用サンプルアプリはこちら。
Mac 用と Windows 用のキャプティブランタイム AIR アプリを一緒にアーカイブしてるのでちょっと容量が大きいです…