えへへ

うふふ

ヒデタロ先輩にご紹介にあずかりました、
acha_maroことアチャマロです!

早速ですが、
前にPHPでTwitterからストリーミングを中継して、 flashで受け取るというのをやりました。
まずは、Twitterからのストリーミングを各クライアントのソケットに流し込むところまで。

AMS.php(AchamaroMediaServer)


<?php
// Twitter User ID
$id = "userid";
// Twitter User Pass
$pass = "password";
// Twitter Streaming API
$streamingAPI = "http://stream.twitter.com/1/statuses/filter.json";
// Listenポート
$port = 5080;

// APIパラメータ
$context = stream_context_create
(
	array(
		'http' => array(
			'method'  => "POST",
			'header'  => "Authorization: Basic " . base64_encode($id . ":" . $pass) . "\r\n" .
						 "Content-type: application/x-www-form-urlencoded" . "\r\n",
			'content' => http_build_query(
				array(
					'track' => "#achamaro"
                                        // #achamaroを含むツイートを受信
				)
			)
		)
	)
);

// Listen開始
$serversocket = socket_create_listen($port);
socket_set_nonblock($serversocket);

// クライアントソケット格納用配列
$clients = array();

// ストリーミング受信開始
$stream = fopen($streamingAPI, 'r', false, $context);

while ($json_text = fgets($stream)) {

	// 新規クライアント接続
	while (false !== ($tmp_socket = @socket_accept($serversocket))) {
		$clients[] = $tmp_socket;
	}

	// JSONデコード
	$json = json_decode($json_text, true);

	if (!$json) continue;

	// とりあえずツイートを各クライアントへ送信
	foreach ($clients as $client) {
		@socket_write($client, $json['text'], strlen($json['text']));
	}

}
?>


ここまでは割といろんなブログで公開されているので
とくに問題なく進みました。

動作確認は

コンソールから

$php AMS.php

別コンソールから

$telnet localhost 5080

後は、ツイッターで「#achamaro」をつけてつぶやいた瞬間に
2個目のコンソールに表示されればOKです。

次にflash側です。

まず、flashでツイート表示用のテキストフィールドを作成し、
インスタンス名に「tBox」と名付けました。
表示先の準備が出来たのでActionScriptを書いていきます。

socket.as ※socket.asはドキュメントクラスです。

	import flash.display.MovieClip;
	import flash.net.Socket;
	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
		
	public class socket extends MovieClip
	{
		// ソケットオブジェクト
		private var sk:Socket;
		
		/**
		 * コンストラクタ
		 */
		public function socket()
		{
			// AMSに接続
			this.sk = new Socket("192.168.1.31",5080);
			
			// 接続確立イベントハンドル
			this.sk.addEventListener(Event.CONNECT,connectHandler);
			// セキュリティエラーイベントハンドル
			this.sk.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityErrorHandler);
			// 受信イベントハンドル
			this.sk.addEventListener(ProgressEvent.SOCKET_DATA,progressHandler);
		}
		
		/**
		 * セキュリティイベントハンドラー
		 */
		private function securityErrorHandler(event:SecurityErrorEvent)
		{
			// デバッグ
			this.tBox.appendText("securityError: " + event);
		}
		
		/**
		 * 接続確立イベントハンドラー
		 */
		private function connectHandler(event:Event)
		{
			// デバッグ
			this.tBox.appendText("connect:" + event);
		}
		
		/**
		 * 受信イベントハンドラー
		 */
		private function progressHandler(event:ProgressEvent)
		{
			// デバッグ
			this.tBox.appendText("progress: " + event);
			// 受信内容表示
			readResponse();
		}
		
		/**
		 * 受信内容表示
		 */
		private function readResponse()
		{
			var str:String = this.sk.readUTFBytes(this.sk.bytesAvailable);
			this.tBox.appendText(str);
		}
	}

flashで実行してみて受信できたのでパブリッシュ!
複数のブラウザで受信してみようとサーバにあげてみたところ


securityError: [SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048: セキュリティサンドボックス侵害 : http://192.168.1.31:1002/socket.swf は 192.168.1.31:5080 からデータを読み込めません。"]

というエラーが。。。
試しにクロスドメインXMLを置いてみましたがダメ。。。

as3 + socket とかでググっていると
どうやらポリシーファイルというクロスドメインとは別ものを
置いてあげる必要があるみたいでした。

Flashのソケットポリシーファイルを参考にさせて頂きました。

どうやらflashが843番ポートを覗きに来るので
ソケットポリシーファイルを返してあげないといけないようです。

早速ソケットポリシーファイル作成

poricy.xml

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
    <allow-access-from domain="*" to-ports="5080"/>
</cross-domain-policy>


次に843番ポートでporicy.xmlを返すPHPプログラムを組みます。

poricy.php

<?php
$xml = file_get_contents('poricy.xml');

$port = 843;
$server = socket_create_listen($port);

while (true) {
	$client = @socket_accept($server);
	@socket_write($client, $xml, strlen($xml));
	@socket_close($client);
}
socket_close($server);
?>

AMS.phpもやったし簡単^ω^v

コンソールからporicy.phpを実行!

$php poricy.php


PHP Warning: socket_create_listen(): unable to bind to given adress [13]: Permission denied in /var/www/socket/htdocs/poricy.php on line 6

むむむ!
AMS.phpの時はエラーとか出なかったのに。。。
そうえいばポート1000番以内はどうのこうのとか聞いた事がある気がしたので、
試しにrootで実行

エラーなし!
ブラウザのキャッシュクリアして再読み込み
無事受信できました。