2016年8月4日 星期四

PHP Xampp 實作 websocket 步驟紀錄

本來只是幫人找一下php上如何實作一個簡單的websocket
沒想到找到的各種資料都不太一樣還頗麻煩的
好不容易成功了當然要記錄下來
免得下次要蓋還得再查一圈



以下相當不專業的PHP建立流程:

1.下載安裝Xampp
   這步驟應該不會有什麼問題所以跳過~

2.開啟Xampp
   打開Xampp的control panel,把apache打開
   php的跟目錄在[xampp path] / htdocs / 下
   這部分也應該不會有什麼問題,跳過

接下來的部分都是參考這個網誌來進行的

3.建立工作目錄
   先在htdoc下開一個websocket server用的資料夾
   例如說這邊也參考來源網誌開了一個叫ws的資料夾

4.安裝Composer
   在websocket server用的資料夾安裝Composer
   在這個資料夾下打開cmd(命令提示字元)
   然後照順序執行以下四行指令(來源:Composer官網)

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === 'e115a8dc7871f15d853148a7fbac7da27d6c0030b848d9b3dc09e2a0388afed865e6a3d6b3c0fad45c48e2b5fc1196ae') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

   這個composer我也不清楚是什麼,初步猜測是類似ubuntu的apt-get那種協助安裝各種套件的東西~

5.安裝Ratchet
   接著透過Composer在這個目錄安裝Ratchet
   同樣在此資料夾打開cmd
   然後執行以下兩個指令

php composer.phar require cboden/ratchet
php composer.phar install

   完成到這邊時,資料夾裡面應該已經多出一個叫vendor的資料夾以及三個composer的檔案

6.建立資料夾與檔案
   首先在資料夾中建立一個資料夾叫src
   用來放等等要建立的Namespace以及相關程式
   同時在建立一個資料夾叫bin
   用來存放真正用來執行監控socket的程式

   在src資料夾中建立一個新的資料夾
   資料夾的名稱設定什麼都可以
   這會是等等需要用到的Namespace名稱(這邊參照元來源網誌取名叫MyApp)
   然後在MyApp資料夾中建立一個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();
    }
}

   這支是websocket裡面的事件主程式
   裡面的$client有點類似Java裡socket的Array

   接著回到bin目錄下建立一個檔案叫chat-server.php
   裡面的內容如下:

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

   這隻就是真的用來執行的server了
 
   建立好的檔案結構應該會像這樣(名稱採範例的名稱)
   htdoc
   └ ws
       ├ bin
       │ └ chat-server.php
       ├ src
       │ └ MyApp
       │   └ Chat.php
       ├ vendor
       ├ composer.json
       ├ composer.lock
       └ composer.phar

7.修改composer.json
   在真正執行server前請打開檢查composer.json這個檔案
   確保裡面的結構如下("MyApp"部分會因為每個人設定的Namespace不同而不同):


{

 "autoload": {

        "psr-0": {

            "MyApp": "src"

        }

    },

    "require": {

        "cboden/ratchet": "^0.3.5"

    }

}

   如果打開後不是長這樣
   請修改成上述的正確內容後
   在資料夾下打開cmd
   執行以下指令:

composer dumpautoload

8.執行server
   到這邊已經將server建立完成了
   只要把server打開就可以開始監聽了
   打開的方式是到bin資料夾中打開cmd
   執行以下指令:

php chat-server.php

   成功執行的話cmd的畫面會卡在那邊不動
   這是正常的,目前的程式沒有設定任何成功開始監聽的訊息
   請不要關掉它,關掉監聽也就跟著結束了

9.建立前端網頁
   在htdoc底下建立一支網頁(名稱隨意)
   裡面內容如下:

<!DOCTYPE html>
<html>
<head>
 <title>Ratchet Test</title>
 <script src="http://code.jquery.com/jquery-1.10.0.min.js"></script>
 <script>
  
  var messages = [];
 
  // connect to the socket server
  var chat_conn = new WebSocket('ws://localhost:8080');
  chat_conn.onopen = function(e) {
   console.log('Connected to server:', chat_conn);
  }
   
  chat_conn.onerror = function(e) {
   console.log('Error: Could not connect to server.');
  }
   
  chat_conn.onclose = function(e) {
   console.log('Connection closed');
  }
   
  // handle new message received from the socket server
  chat_conn.onmessage = function(e) {
   // message is data property of event object
   var message = JSON.parse(e.data);
   console.log('message', message);
   
   // add to message list
   var li = '<li>' + message.text + '</li>';
   $('.message-list').append(li);
  }
   
  // attach onSubmit handler to the form
  $(function() {
   $('.message-form').on('submit', function(e) {
    // prevent form submission which causes page reload
    e.preventDefault();
   
    // get the input
    var input = $(this).find('input');
   
    // get message text from the input
    var message = {
     type: 'message',
     text: input.val()
    };
   
    // clear the input
    input.val('');
   
    // send message to server
    chat_conn.send(JSON.stringify(message));
   });
  });
 
 </script>
</head>
<body>
 
 <h1>Chat App Using Ratchet</h1>
 
 <h2>Messages</h2>
 <ul class="message-list"></ul>
 <form class="message-form">
  <input type="text" size="40" placeholder="Type your message here" />
  <button>Post it!</button>
 </form>
 
</body>
</html>

   然後用兩個不同的分頁或瀏覽器打開這個網頁
   就可以發送訊息給自己以外的連線對象了

1 則留言 :