swoole websocket服务推送


用过workerman, 两个字"好用",对于swoole最近有时间也研究研究

swoole的websocket 很好实现

如官网 https://wiki.swoole.com/wiki/page/479.html

ws_server.php

//创建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();

运行程序

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了!

现在我们看到的是客户端发送信息,服务器应答并返回数据

那我们现在要的是服务器主动发送信息

有三个办法:

1.使用swoole的定时器,定时发送,可通过syc从数据库获取数据逻辑判断后push发送给客户端

2.使用swoole中自带框架

这个方法和方法3原理是一样的,就是需要后台主动推送的时候,模拟一个客户端发送消息,可以是CLI的脚本,也可以是php的CURL请求

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

github下载地址: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



    
        
        Title
    
    
        

运行

php ser.php