swoole websocket服務推送

用過workerman, 兩個字"好用",對於swoole最近有時間也研究研究php

swoole的websocket 很好實現html

如官網 https://wiki.swoole.com/wiki/page/479.htmlgit

ws_server.phpgithub

//建立websocket服務器對象,監聽0.0.0.0:9502端口
$ws = new swoole_websocket_server("0.0.0.0", 9502);

//監聽WebSocket鏈接打開事件
$ws->on('open', function ($ws, $request) {
    var_dump($request->fd, $request->get, $request->server);
    $ws->push($request->fd, "hello, welcome\n");
});

//監聽WebSocket消息事件
$ws->on('message', function ($ws, $frame) {
    echo "Message: {$frame->data}\n";
    $ws->push($frame->fd, "server: {$frame->data}");
});

//監聽WebSocket鏈接關閉事件
$ws->on('close', function ($ws, $fd) {
    echo "client-{$fd} is closed\n";
});

$ws->start();

 

運行程序web

php ws_server.php

客戶端 a.html數據庫

var wsServer = 'ws://127.0.0.1:9502';
var websocket = new WebSocket(wsServer);
websocket.onopen = function (evt) {
    console.log("Connected to WebSocket server.");
};

websocket.onclose = function (evt) {
    console.log("Disconnected");
};

websocket.onmessage = function (evt) {
    console.log('Retrieved data from server: ' + evt.data);
};

websocket.onerror = function (evt, e) {
    console.log('Error occured: ' + evt.data);
};

ok了!服務器

如今咱們看到的是客戶端發送信息,服務器應答並返回數據websocket

那咱們如今要的是服務器主動發送信息

有三個辦法:swoole

1.使用swoole的定時器,定時發送,可經過syc從數據庫獲取數據邏輯判斷後push發送給客戶端app

2.使用swoole中自帶框架

這個方法和方法3原理是同樣的,就是須要後臺主動推送的時候,模擬一個客戶端發送消息,能夠是CLI的腳本,也能夠是php的CURL請求

https://github.com/matyhtf/framework/blob/master/libs/Swoole/Client/WebSocket.php

github下載地址: https://github.com/matyhtf/framework

<?php
define('DEBUG', 'on');
define("WEBPATH", str_replace("\\", "/", __DIR__));
require __DIR__ . '/framework-master/libs/lib_config.php';
$client = new Swoole\Client\WebSocket('127.0.0.1', 9502);
if (!$client->connect()) {
    echo "connect to server failed.\n";
    exit;
}

  $client->send("我是PHP-client端,發來的消息");  # 客戶端能夠看到

3.設置onRequest回調

用過workerman的都知道,workerman中就有這個獲取http的get,post 數據並sendto客戶端,在這裏swoole也能夠實現

https://wiki.swoole.com/wiki/page/397.html

swoole_websocket_server 繼承自 swoole_http_server

    • 設置了onRequest回調,websocket服務器也能夠同時做爲http服務器
    • 未設置onRequest回調,websocket服務器收到http請求後會返回http 400錯誤頁面
    • 若是想經過接收http觸發全部websocket的推送,須要注意做用域的問題,面向過程請使用「global」對swoole_websocket_server進行引用,面向對象能夠把swoole_websocket_server設置成一個成員屬性

代碼以下

ser.php

<?php

class MyWebsocket {

    private $server;
    private $fid=[];
    # run()
    public function toRun() {
        $this->server = new swoole_websocket_server("0.0.0.0", 9502, SWOOLE_BASE, SWOOLE_SOCK_TCP); //SWOOLE_SSL  須要ssl才加
        #監聽WebSocket鏈接打開事件
        $this->server->on('open', function ($server, $request) {
            $this->server->push($request->fd, "hello, welcome ID:{$request->fd}\n");
            $this->fid[]=$request->fd;   # $request->fd fd 
        });
        #監聽WebSocket消息事件
        $this->server->on('message', function ($server, $frame) {   #$frame->data 消息內容
            $msg = 'from' . $frame->fd . ":{$frame->data}\n";
            foreach ($this->fid as $fd) {
                $server->push($fd, $msg);
            }
        });

        //監聽WebSocket鏈接關閉事件
        $this->server->on('close', function($ws, $fd) {
        $fd_key = array_search($fd, $this->fid ? $this->fid : []);
        $key_zero = isset($this->fid[0]) && $this->fid[0] == $fd ? TRUE : FALSE;  # key=0 
        if ($fd_key || $key_zero) {
            unset($this->fid[$fd_key]);
        }
        echo "client-{$fd} is closed\n";
    });

        #onRequest回調    http://127.0.0.1:9502/?sendto=1,20,3&message=%E4%BD%A0%E5%A5%BD
        $this->server->on('request', function ($req, $respone) {
            # get 兩個參數, userid ","  發送消息
            $list=[];
            if (isset($req->get['sendto']) && isset($req->get['message'])) {
                $user = explode(',', $req->get['sendto']);
                $list = array_intersect($this->fid, $user);
                if (!empty($list)) {
                    foreach ($list as $fd) {
                        $this->server->push($fd, $req->get['message']);
                    }
                }
            }
            $total= count($this->fid);
            $sendSum= count($list);
              $respone->end("Current fid:{$respone->fd},  OnLine:{$total}, Send:{$sendSum}");    
            
        });

        $this->server->start();
    }

   

}

$app = new MyWebsocket();
$app->toRun();

 

客戶端html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <div id="msg"></div>
        <input type="text" id="text">
        <input type="submit" value="發送數據" onclick="sending()">
    </body>
    <script>
        var msg = document.getElementById("msg");
        var wsServer = 'ws://127.0.0.1:9502';
        //調用websocket對象創建鏈接:
        //參數:ws/wss(加密)://ip:port (字符串)
        var websocket = new WebSocket(wsServer);
        //onopen監聽鏈接打開
        websocket.onopen = function (evt) {
            //websocket.readyState 屬性:
            /*
             CONNECTING    0    The connection is not yet open.
             OPEN    1    The connection is open and ready to communicate.
             CLOSING    2    The connection is in the process of closing.
             CLOSED    3    The connection is closed or couldn't be opened.
             */
            console.log(websocket.readyState);
        };

        function sending() {
            var text = document.getElementById('text').value;
            document.getElementById('text').value = '';
            //向服務器發送數據
            websocket.send(text);
        }
        //監聽鏈接關閉
        websocket.onclose = function (evt) {
            msg.innerHTML+="Disconnected<br>";
        };

        //onmessage 監聽服務器數據推送
        websocket.onmessage = function (evt) {
            msg.innerHTML += evt.data + '<br>';
            console.log('Retrieved data from server: ' + evt.data);
        };
        //監聽鏈接錯誤信息
        websocket.onerror = function (evt, e) {
            console.log('Error occured: ' + evt.data);
        };

    </script>
</html>

 

運行

php ser.php 

相關文章
相關標籤/搜索