RecentChanges

  • 2014-07-08 (火) 21:11:48 – エラーログの場所
  • 2014-07-08 (火) 14:59:17 – phpMyAdmin 大きなデータをインポートする
  • 2014-07-08 (火) 11:10:51 – HTML Chromeブラウザ 画像のheightを100%にすると、おかしくなる
  • 2014-07-07 (月) 12:50:52 – Nexus4をDocomoのSIMカードで使う
  • 2014-07-07 (月) 09:54:23 – ホームページ上でテロップのように文字を流す
  • 2014-07-04 (金) 18:11:41 – Photoshop 表示していないレイヤーを一度に削除する
  • 2014-07-04 (金) 15:49:36 – SQLで緯度・経度から2点間の距離を算出する
  • 2014-07-04 (金) 14:28:15 – MySQL バイナリログの内容を確認する
  • 2014-07-04 (金) 09:57:08 – Gmail 件名を変えて返信
  • 2014-07-04 (金) 00:52:17 – OpenOffice
  • 2014-07-03 (木) 12:06:39 – IE8 Jpegが見れない
  • 2014-07-02 (水) 20:46:00 – HTML チェックを付けたら値が入る方法
  • 2014-07-02 (水) 20:40:45 – PHP 日時のデータから時分のみ取り出して整形するサンプルコード
  • 2014-07-01 (火) 23:55:04 – 無料で使うマイクロソフトOffice
  • 2014-07-01 (火) 16:26:44 – MySQL 日本語文字化け対策2
  • 2014-07-01 (火) 15:05:19 – CakePHP 繰り返す見た目を別ファイルにする
  • 2014-06-30 (月) 12:37:18 – Node.jsでTCPサーバー・クライアントを作る
  • 2014-06-29 (日) 22:31:06 – phpMyAdmin データベースの情報などを出力する
  • 2014-06-27 (金) 16:05:19 – cakePHP トランザクションを使う
  • 2014-06-27 (金) 13:31:05 – 記事内にアンケートフォームを作るプラグイン
  • 2014-06-27 (金) 11:17:50 – Eclipse 既存のソースコードから新規プロジェクトをつくる
  • 2014-06-27 (金) 10:52:54 – MySQL グループの中の最大値のデータを取得
  • 2014-06-26 (木) 22:22:18 – 1台のPCの画面を2台のモニターで見る
  • 2014-06-26 (木) 17:23:01 – Android スピナー デザイン性のあるスピナー サンプルコード
  • 2014-06-26 (木) 03:35:11 – UITableViewCellの高さを可変にする
  • 2014-06-24 (火) 22:03:31 – MapboxとMapQuestライセンスと料金比較
  • 2014-06-24 (火) 14:36:51 – phpMyAdmin よく書くSQL文を保存しておく
  • 2014-06-24 (火) 13:36:40 – Eclipse subversion ディレクトリがSwitchになってしまった時
  • 2014-06-24 (火) 09:10:18 – Outlook2007で、スペースの「□」や改行マークを非表示にしたい
  • 2014-06-23 (月) 18:43:34 – リダイレクト Javascriptとmetaタグどちらが早い
  • 2014-06-23 (月) 16:14:05 – Facebook ファンページのウォールをホームページに埋め込む
  • 2014-06-23 (月) 13:10:15 – css background-position が効かない
  • 2014-06-23 (月) 06:03:58 – phpMyAdmin MySQLのプロセスを停止する
  • 2014-06-20 (金) 21:03:18 – WordPress 手動で更新する方法
  • 2014-06-20 (金) 12:29:00 – PukiWIki Runtime error Error message cannot write ./attach/(237文字).log
  • 2014-06-20 (金) 11:48:44 – Android ListViewの項目をタップして関連する内容を入力してListViewに戻る サンプルコード
  • 2014-06-20 (金) 08:37:39 – Eclipse android import Invalid project description
  • 2014-06-19 (木) 16:26:08 – Cake PHP 電話番号のバリデーションルール
  • 2014-06-18 (水) 18:24:47 – Flashの下にプルダウンメニューが隠れてしまう
  • 2014-06-18 (水) 17:30:21 – .htaccessが利用できない
  • 2014-06-18 (水) 16:03:39 – Google Map Android Api Ver2 で地図が表示されない!!?
  • 2014-06-18 (水) 00:28:59 – Android versionCodeとversionNameの違い
  • 2014-06-17 (火) 19:35:19 – ListViewの中にCheckBoxを入れるとsetOnItemClickListenerが動作しない
  • 2014-06-17 (火) 14:00:38 – Google Spreadsheetのセル内で改行
  • 2014-06-16 (月) 17:39:03 – 自動で一定時間後パスワードロックをかける
  • 2014-06-16 (月) 17:19:45 – The meta-data tag in your app’s AndroidManifest.xml does not have the right value
  • 2014-06-16 (月) 11:30:40 – iPhone 構成ユーティリティのインストール方法と使い方
  • 2014-06-15 (日) 17:14:22 – Google Map mapが表示されない
  • 2014-06-13 (金) 21:31:10 – Mapbox 地図の色などを変えてみる
  • 2014-06-13 (金) 21:24:24 – Mapbox サイトにMapboxを埋め込む サンプルコード有り
  • 2014-06-13 (金) 21:12:59 – Mapbox
  • 2014-06-13 (金) 21:11:17 – Mapbox Welcome to Mapboxを消す
  • 2014-06-13 (金) 17:58:59 – paddingがtableできかない
  • 2014-06-13 (金) 16:21:25 – java.lang.NoSuchMethodError android.os.Bundle.getString
  • 2014-06-13 (金) 15:59:10 – SCRIPT1028 識別子、文字列または数がありません。
  • 2014-06-13 (金) 14:22:12 – Chrome 文字化けを防ぐ
  • 2014-06-12 (木) 15:42:58 – Googleデスクトップ 検索する場所を追加
  • 2014-06-12 (木) 14:28:05 – WordPress Contact Form 7 宛先を複数にする
  • 2014-06-12 (木) 13:08:11 – Google Play アルファ版機能を利用してアプリをテストする
  • 2014-06-12 (木) 13:07:42 – Android リリースしたアプリの月額課金をテストする

#norelated

Ratchetを利用してPHPでWebソケット 2 デプロイ編

Javascript

以前に
Ratchetを利用してPHPでWebソケット 1
ということで、Ratchetを使ってWebソケットを実装しようというのをやりましたが、それから半年以上たって、やっとデプロイするときがやってきました。(゜∀゜)
時間空きすぎて、Ratchetのことをほとんど覚えていなかった…。
しかし、Ratchetを利用してPHPでWebソケット 1の記事が役に立ったことは言うまでもありません。

下記のサイトに親切にデプロイのやり方が書いてあるので、盲目的にまずやってみます。
http://socketo.me/docs/deploy

まず、HAProxyというものを導入します。
http://www.haproxy.org/

ググるとロードバランサーとしてご利用の方が多そうですが、これをつまりWebsocketと別のポートで接続しなくてもよいようにするために利用します。

これだけで、それなりのボリュームになりそうなので、
Linux初心者がHAProxyを導入する
という記事に書いておきます。

次に、Supervisorというプロセス管理ツールを入れます。
これは、Ratchetを永遠にw生かしておくために入れます。
Linux初心者がSupervisorを導入する

で、デプロイのコードを簡潔に書こうと思います。

構造は下記の通りです。

 Ratchet
   |  
   ---bin
   |   --chat-server,php
   |   --push-server.php
   |
   ---src
       --MyApp
          --Chat.php
          --entry.php
          --Pusher.php

ちなみに、HAProxyによって、Webソケットはポート番号1337ですので、各コードの中で1337を指定しています。
詳しくはここを見てくれってばよ→Linux初心者がHAProxyを導入する

上から順に行きます。

chat-server.php

 <?php
 use Ratchet\Server\IoServer;
 use MyApp\Chat;
 
    require dirname(__DIR__) . '/vendor/autoload.php';
 
    $server = IoServer::factory(
        new Chat(),
        1337
    );
 
    $server->run();
 ?>

push-server.php

 <?php
    require dirname(__DIR__) . '/vendor/autoload.php';
 
    $loop   = React\EventLoop\Factory::create();
    $pusher = new MyApp\Pusher;
 
    // Listen for the web server to make a ZeroMQ push after an ajax request
    $context = new React\ZMQ\Context($loop);
    $pull = $context->getSocket(ZMQ::SOCKET_PULL);
    $pull->bind('tcp://127.0.0.1:5555'); // Binding to 127.0.0.1 means the only client that can connect is itself
    $pull->on('message', array($pusher, 'onBlogEntry'));
 
    // Set up our WebSocket server for clients wanting real-time updates
    $webSock = new React\Socket\Server($loop);
    $webSock->listen(1337, '0.0.0.0'); // Binding to 0.0.0.0 means remotes can connect
    $webServer = new Ratchet\Server\IoServer(
        new Ratchet\Http\HttpServer(
            new Ratchet\WebSocket\WsServer(
                new Ratchet\Wamp\WampServer(
                    $pusher
                )
            )
        ),
        $webSock
    );
 
    $loop->run();

Chat.php

 <?php
 namespace MyApp;
 use Ratchet\MessageComponentInterface;
 use Ratchet\ConnectionInterface;
 
 class Chat implements MessageComponentInterface {
    protected $clients;
 
    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }
 
    public function onOpen(ConnectionInterface $conn) {
        // Store the new connection to send messages to later
        $this->clients->attach($conn);
 
        echo "New connection! ({$conn->resourceId})\n";
    }
 
    public function onMessage(ConnectionInterface $from, $msg) {
        $numRecv = count($this->clients) - 1;
        echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
            , $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');
 
        foreach ($this->clients as $client) {
            if ($from !== $client) {
                // The sender is not the receiver, send to each client connected
                $client->send($msg);
            }
        }
    }
 
    public function onClose(ConnectionInterface $conn) {
        // The connection is closed, remove it, as we can no longer send it messages
        $this->clients->detach($conn);
 
        echo "Connection {$conn->resourceId} has disconnected\n";
    }
 
    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "An error has occurred: {$e->getMessage()}\n";
 
        $conn->close();
    }
 }

entry.php …今回、本体のWebアプリはCakePHP3で作っていますが本体と連動しているのがこいつです。

 <?php
 //CakePHPからincludeで呼び出しされて利用される
 
 ini_set( 'display_errors', 1 ); 
 
    $entryData = array(
        'category' => "id".$shipper_id
      , 'title'    => $title
      , 'article'  => 'hogeraccho'
      , 'when'     => time()
    );
    
    
    // This is our new stuff
    $context = new ZMQContext();
    $socket = $context->getSocket(ZMQ::SOCKET_PUSH, 'my pusher');
    $socket->connect("tcp://localhost:5555");
 
    $socket->send(json_encode($entryData));
    

Pusher.php

 <?php
 namespace MyApp;
 use Ratchet\ConnectionInterface;
 use Ratchet\Wamp\WampServerInterface; 
 
 class Pusher implements WampServerInterface {
 
    /**
     * A lookup of all the topics clients have subscribed to
     */
    protected $subscribedTopics = array();
 
    public function onSubscribe(ConnectionInterface $conn, $topic) {
        $this->subscribedTopics[$topic->getId()] = $topic;
    }
 
    /**
     * @param string JSON'ified string we'll receive from ZeroMQ
     */
    public function onBlogEntry($entry) {
        $entryData = json_decode($entry, true);
 
        // If the lookup topic object isn't set there is no one to publish to
        if (!array_key_exists($entryData['category'], $this->subscribedTopics)) {
            return;
        }
 
        $topic = $this->subscribedTopics[$entryData['category']];
 
        // re-send the data to all the clients subscribed to that category
        $topic->broadcast($entryData);
    }
 
    public function onUnSubscribe(ConnectionInterface $conn, $topic) {
    }
    public function onOpen(ConnectionInterface $conn) {
    }
    public function onClose(ConnectionInterface $conn) {
    }
    public function onCall(ConnectionInterface $conn, $id, $topic, array $params) {
        // In this application if clients send data it's because the user hacked around in console
        $conn->callError($id, $topic, 'You are not allowed to make calls')->close();
    }
    public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible) {
        // In this application if clients send data it's because the user hacked around in console
        $conn->close();
    }
    public function onError(ConnectionInterface $conn, \Exception $e) {
    }
 }

bin/push-server.php
をSupervisorでの設定により、起動させることによって、Ratchetが常時動作します。
詳しくは→Linux初心者がSupervisorを導入する

Ratchetを利用してPHPでWebソケット 1

PHP

一つの課題がありまして、PHPでもうすでにできあがっているプログラムがあり、でもWebsocketでリアルタイム通信をしたいという課題です。

弊社では、今までWebsocketでリアルタイム通信をするとき、node.jsをよく利用していました。
が、すでにあるプログラム群に追加するのはいろいろと面倒だったのです。

そこで、Ratchet WebSockets for PHPなるものがあることがわかりました。
http://socketo.me/

ほほー
これは、私が求めているものに近い!!
しかも、解説が親切!

というわけで、とりあえず、最初のチュートリアルからやってみます。

“hello world”やってみよう、という公式サイトを初心者目線で解説してみます。
http://socketo.me/docs/hello-world

とりあえず、例として、サーバーの下記のパスにratchetを入れてみます。

 /var/www/html/test/ratchet/

まず、PSR-0というライブラリとか、Ratchetのライブラリを入手します。
こういうのは、今時はもうcomposerでさくっとやっちゃうのです⊂(^-^)⊃

composerの例文がありますね。

 {
    "autoload": {
        "psr-0": {
            "MyApp": "src"
        }
    },
    "require": {
        "cboden/ratchet": "0.3.*"
    }
 }

ちなみに、PSR-0のサイトへ行くと、PSR-4を使ってくれよーん(2016年5月2日現在)と書いてあるので、気を利かしてpsr-4とやっても、ratchetさんのほうで対応していないので、動きません!

上記をテキストファイルに書いて、composer.jsonという名前でサーバーにアップロードします。

 $ composer update

とやります。

あとはですね、/var/www/html/test/ratchet/の中に、src/MyAppというディレクトリを作って、その中にChat.phpという名前で次のPHPファイルを保存します。

 <?php
 namespace MyApp;
 use Ratchet\MessageComponentInterface;
 use Ratchet\ConnectionInterface;
 
 class Chat implements MessageComponentInterface {
    protected $clients;
 
    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }
 
    public function onOpen(ConnectionInterface $conn) {
        // Store the new connection to send messages to later
        $this->clients->attach($conn);
 
        echo "New connection! ({$conn->resourceId})\n";
    }
 
    public function onMessage(ConnectionInterface $from, $msg) {
        $numRecv = count($this->clients) - 1;
        echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
            , $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');
 
        foreach ($this->clients as $client) {
            if ($from !== $client) {
                // The sender is not the receiver, send to each client connected
                $client->send($msg);
            }
        }
    }
 
    public function onClose(ConnectionInterface $conn) {
        // The connection is closed, remove it, as we can no longer send it messages
        $this->clients->detach($conn);
 
         echo "Connection {$conn->resourceId} has disconnected\n";
    }
 
    public function onError(ConnectionInterface $conn, \Exception $e) {
         echo "An error has occurred: {$e->getMessage()}\n";
 
        $conn->close();
    }
 }

次に、/var/www/html/test/ratchet/の中に、binというディレクトリを作って、その中にchat-server.phpという名前で次のPHPファイルを保存します。

 <?php
 use Ratchet\Server\IoServer;
 use MyApp\Chat;
 
    require dirname(__DIR__) . '/vendor/autoload.php';
 
    $server = IoServer::factory(
        new Chat(),
        8080
    );
 
    $server->run();

サーバーで、次のようにやります。

 $ php bin/chat-server.php

Windowsで、コマンドプロンプトを立ち上げます。
hogehoge.netというサーバーに上記の設定をしたとすると、

 telnet hogehoge.net 8080

とやります。
ちなみに、デフォルトでWindows10にTelnetは無効化されてますので、下記の記事を参考に有効化してください。
Windows10 Telnetを使う

もう一つ、コマンドプロンプトを立ち上げます。

 telnet hogehoge.net 8080

とやります。

すると、一方の画面で文字を打つと…
もう一方の画面にでてくるんですね!!
すごい!
感動ひとしお!!!

  • aaaaa — bbbbb {2018-01-07 (日) 08:24:57}