Swoole-WebSocket服務端主動推送消息

Swoole-WebSocket服務端主動推送消息

標籤(空格分隔): websocket swoole php

swoole-request.jpg

WebSocket服務器代碼

<?php
namespace swoole\websocket;

class WebSocketServer
{

    var $server;

    public function __construct()
    {
        $this->server = new \Swoole\WebSocket\Server("0.0.0.0", 9991);
        print "WebSocketServer: 0.0.0.0, 9991" . PHP_EOL;
        $this->server->set([
            'task_worker_num' =>4
        ]);
        $this->server->on('open', [$this, 'open']);
        $this->server->on('message', [$this, 'message']);
        $this->server->on('task', [$this, 'task']);
        $this->server->on('finish', [$this, 'finish']);
        $this->server->on('request', [$this, 'request']);
        $this->server->on('close', [$this, 'close']);
        $this->server->start();
    }


    /**
     * $request 是一個 HTTP 請求對象,包含了客戶端發來的握手請求信息
     * onOpen 事件函數中可以調用 push 向客戶端發送數據或者調用 close 關閉連接
     * onOpen 事件回調是可選的
     * @param \Swoole\WebSocket\Server $server
     * @param \Swoole\Http\Request $request
     */
    public function open($server, $request)
    {
        $fd = $request->fd;
        echo "server: handshake success with fd{$fd}" . PHP_EOL;
    }


    /**
     * $frame 是 Swoole\WebSocket\Frame 對象,包含了客戶端發來的數據幀信息
     * onMessage 回調必須被設置,未設置服務器將無法啓動
     * 客戶端發送的 ping 幀不會觸發 onMessage,底層會自動回覆 pong 包,也可設置 open_websocket_ping_frame 參數手動處理
     * @param \Swoole\WebSocket\Server $server
     * @param \Swoole\WebSocket\Frame $frame
     */
    public function message($server, $frame)
    {
        $data = json_decode($frame->data, true);
        var_dump("---收到消息----fd:{$frame->fd}");
        var_dump($data);
        $server->task($data);

        // 保持連接 心跳檢測
        if ($data['type'] == 'ping') {
            $server->push($frame->fd, json_encode(['type' => 'ping', 'data' => 'tong']));
        }
    }

    /**
     * @param \Swoole\WebSocket\Server $server
     * @param $fd
     */
    public function close($server, $fd)
    {
        echo "fd:{$fd} close" . PHP_EOL;
    }


    /**
     * @param \Swoole\Server $server
     * @param int $taskId
     * @param int $srcWorkerId
     * @param mixed $data
     */
    public function task($server, $taskId, $srcWorkerId, $data)
    {
        echo "正在處理任務----taskId:{$taskId}" . PHP_EOL;
        sleep("3");
        $server->finish("ok");
    }


    /**
     * @param \Swoole\Server $server
     * @param int $task_id
     * @param mixed $data
     */
    public function finish($server, $taskId, $data)
    {
        echo "任務處理成功-----taskId:{$taskId}";
    }


    public function request(\Swoole\Http\Request $request, \Swoole\Http\Response $response)
    {
        echo "服務端主動推送消息......" . PHP_EOL;
        if ($request->server['path_info'] == "/websocket/") {
            foreach ($this->server->connections as $fd) {
                if ($this->server->isEstablished($fd)) {
                    $this->server->push($fd, json_encode(['type' => 3, 'data' => '系統消息推送' . mt_rand(1000, 9999)]));
                }
            }
        }
    }
}

new WebSocketServer();

客戶端(JS)

<script>
document.addEventListener("DOMContentLoaded", function() {
    var wsServer = 'ws://web.test.com/wss';
    var websocket = new WebSocket(wsServer);
    websocket.onopen = function (evt) {
        console.log("已連接上服務器");
    };

    //每隔5秒鐘發送一次心跳,避免websocket連接因超時而自動斷開
    window.setInterval(function(){
        var ping = {"type":"ping"};
        websocket.send(JSON.stringify(ping));
    },10000);

    websocket.onclose = function (evt) {
        console.log("連接已關閉");
    };

    websocket.onmessage = function (evt) {
        data = eval("("+evt.data+")");
        if (data.type == "ping") {
            return;
        }
        console.log('接受信息: ' + data.data);
    };
});

客戶端(php)

$result = curl_get("http://0.0.0.0:9991/websocket/");
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章