flash on 2013-8-28
ソケット通信のサンプル
@author Hikipuro
/**
* Copyright hayami_susumu ( http://wonderfl.net/user/hayami_susumu )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/AeBv
*/
package
{
import flash.display.ActionScriptVersion;
import flash.display.Graphics;
import flash.display.SimpleButton;
import flash.display.Sprite;
import flash.errors.IOError;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.net.Socket;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFieldType;
import flash.ui.Keyboard;
import flash.utils.ByteArray;
import flash.utils.Endian;
import flash.system.Security;
import flash.system.SecurityPanel;
/**
* ソケット通信のサンプル
* @author Hikipuro
*/
public class Main extends Sprite
{
/**
* 接続先サーバ名
*/
private const server:String = "hiroshi.dnip.net";
/**
* 接続先ポート
*/
private const port:int = 3200;
/**
* セキュリティポリシーファイルを取得するポート
*/
private const policyPort:int = 3210;
/**
* 図形描画用スプライト
*/
private var sprite:Sprite;
/**
* 結果表示用テキストフィールド
*/
private var textField:TextField;
/**
* テキスト入力欄
*/
private var textInput:TextField;
/**
* ボタン
*/
private var button1:SimpleButton;
/**
* ボタンのラベル
*/
private var buttonText1:TextField;
/**
* ソケットオブジェクト
*/
private var socket:Socket;
/**
* ソケットで受信したデータのタイプ
*/
private var packetType:int = 0;
/**
* 文字列を受信した時の文字列長さ
*/
private var stringSize:int = 0;
/**
* 文字列サイズ受信済みフラグ
*/
private var stringSizeReaded:Boolean = false;
// --------------------------------------------------------------------
/**
* コンストラクタ
*/
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
/**
* 初期化イベント
* @param e
*/
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
// ポリシーファイルを取得する
// Flash Player 9 以降? では、ポリシーファイルを xmlsocket:// で取得しないと
// ソケット通信が開始できないようになったそうです。
// http:// で、crossdomain.xml を取得するだけでは
// ソケット通信が許可できないようになっています。
// これは、同一ドメイン内のソケットに接続する場合でも必要になります。
Security.loadPolicyFile("xmlsocket://" + server + ":" + policyPort);
// テキスト入力欄の作成
textInput = new TextField();
textInput.type = TextFieldType.INPUT;
textInput.x = 10;
textInput.y = 210;
textInput.width = 230;
textInput.height = 20;
textInput.border = true;
textInput.borderColor = 0xcccccc;
textInput.addEventListener(KeyboardEvent.KEY_DOWN, onTextInputKeyDown);
addChild(textInput);
// ボタンのラベルの作成
buttonText1 = new TextField();
buttonText1.autoSize = TextFieldAutoSize.CENTER;
buttonText1.selectable = false;
buttonText1.x = 278;
buttonText1.y = 210;
buttonText1.text = "送信";
addChild(buttonText1);
// ボタンの作成
button1 = new SimpleButton();
button1.x = 250;
button1.y = 210;
button1.upState = makeRoundRect(0xDDDDDD, 60, 20, 10);
button1.overState = makeRoundRect(0xFFFFFF, 60, 20, 10);
button1.downState = makeRoundRect(0xBBBBBB, 60, 20, 10);
button1.hitTestState = button1.upState;
button1.addEventListener(MouseEvent.MOUSE_DOWN, onButtonMouseDown);
addChild(button1);
// 結果表示用テキストフィールドの準備
textField = new TextField();
textField.wordWrap = true;
textField.x = 0;
textField.y = 0;
textField.width = 320;
textField.height = 200;
textField.border = true;
textField.borderColor = 0xcccccc;
addChild(textField);
// 図形描画領域の準備
sprite = new Sprite();
sprite.x = 320;
addChild(sprite);
// ソケットオブジェクトを作成
socket = new Socket();
// イベントハンドラ登録
socket.addEventListener(Event.CONNECT, connectHandler);
socket.addEventListener(Event.CLOSE, closeHandler);
socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
// データの並び順を設定
// .net のサーバはリトルエンディアンでデータを扱うので、
// サーバに合わせてリトルエンディアンに設定
socket.endian = Endian.LITTLE_ENDIAN;
// セキュリティサンドボックスタイプの表示
appendText("セキュリティサンドボックスタイプ : " + Security.sandboxType);
// サーバに接続
try {
appendText("接続を開始します。");
socket.connect(server, port);
}
catch (e:Error)
{
appendText("socket.connect() で例外が発生しました。");
appendText(e.toString());
}
}
/**
* テキストフィールドに文字列を追加
*/
private function appendText(text:String):void
{
textField.appendText(text + "\n");
textField.scrollV = textField.maxScrollV;
}
/**
* サーバに、テキスト入力欄のメッセージを送信
*/
private function sendTextMessage():void
{
// 何も入力されてない時はそのまま終了
if (textInput.text == "")
return;
// 未接続の場合はそのまま終了
if (socket.connected == false)
return;
// 入力欄の文字列を ByteArray に入れる
var byteArray:ByteArray = new ByteArray();
byteArray.writeUTFBytes(textInput.text);
byteArray.position = 0;
// 入力されたメッセージをサーバに送信
var string:String = byteArray.readUTFBytes(byteArray.length);
socket.writeByte(2);
socket.writeInt(byteArray.length);
socket.writeUTFBytes(string);
socket.flush();
// 入力欄クリア
textInput.text = "";
}
/**
* 角丸の図形を描いたスプライトを作って返す
* @param color 色
* @param width 幅
* @param height 高さ
* @param round 角丸の大きさ
* @return スプライト
*/
private function makeRoundRect(color:uint, width:int, height:int, round:int):Sprite
{
var s:Sprite = new Sprite();
s.graphics.lineStyle(2);
s.graphics.beginFill(color);
s.graphics.drawRoundRect(0, 0, width, height, round);
s.graphics.endFill();
s.alpha = 0.3;
return s;
}
// --------------------------------------------------------------------
/**
* テキスト入力欄でキーが押された時のイベント
* @param event
*/
private function onTextInputKeyDown(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.ENTER)
sendTextMessage();
}
/**
* 送信ボタンが押された時のイベント
* @param event
*/
private function onButtonMouseDown(event:MouseEvent):void
{
sendTextMessage();
}
/**
* サーバに接続された時のイベント
* @param event
*/
private function connectHandler(event:Event):void
{
appendText("サーバに接続しました。");
}
/**
* ソケットが閉じられた時のイベント
* @param event
*/
private function closeHandler(event:Event):void
{
appendText("接続が閉じられました。");
}
/**
* データ受信イベント
* @param event
*/
private function socketDataHandler(event:ProgressEvent):void
{
var stopFlag:Boolean = false;
// データが 1 バイトでも残っている時はループ
while (socket.bytesAvailable > 0)
{
// データのタイプをチェック
if (packetType == 0)
packetType = socket.readByte();
// タイプごとに処理方法を変える
switch (packetType)
{
// 1 番は、テキスト受信メッセージ
case 1:
stopFlag = onRecieveType1Packet();
break;
// 2 番は、図形描画メッセージ
case 2:
stopFlag = onRecieveType2Packet();
break;
}
// メッセージ受信終了の場合はループを抜ける
if (stopFlag)
break;
}
//trace("bytesAvailable : " + socket.bytesAvailable);
}
/**
* IO エラーイベント
* @param event
*/
private function ioErrorHandler(event:IOErrorEvent):void
{
trace("ioErrorHandler: " + event);
appendText("サーバに接続できませんでした。");
}
/**
* セキュリティエラーイベント
* @param event
*/
private function securityErrorHandler(event:SecurityErrorEvent):void
{
trace("securityErrorHandler: " + event);
appendText("セキュリティエラーが発生しました。");
appendText(event.text);
}
// --------------------------------------------------------------------
/**
* テキストメッセージを受信した時
* @return
*/
private function onRecieveType1Packet():Boolean
{
// 文字数が決定していない時は
// 文字数を受信する
if (stringSizeReaded == false)
{
// 未受信分のデータが 4 バイトより小さい場合は、そのまま終了
if (socket.bytesAvailable < 4)
return true;
// 文字数受信
stringSize = socket.readInt();
stringSizeReaded = true;
}
// 未受信分のデータのバイト数が文字数より小さい場合は、そのまま終了
if (socket.bytesAvailable < stringSize)
return true;
// 指定された文字数分、テキストメッセージを受信
var str:String = socket.readUTFBytes(stringSize);
appendText(str);
stringSizeReaded = false;
stringSize = 0;
packetType = 0;
return false;
}
/**
* 図形描画メッセージを受け取った時
* @return
*/
private function onRecieveType2Packet():Boolean
{
// 未受信分のデータが 20 バイトより小さい場合は、そのまま終了
if (socket.bytesAvailable < 20)
return true;
// 図形の情報を受信
var x:int = socket.readInt();
var y:int = socket.readInt();
var width:int = socket.readInt();
var height:int = socket.readInt();
var color:int = socket.readInt();
// 受信した位置・サイズ・色の図形を描く
var g:Graphics = sprite.graphics;
g.beginFill(color, 0.8);
g.drawRect(x, y, width, height);
g.endFill();
packetType = 0;
return false;
}
}
}