用Swoole快速搭建一个推送服务器

来源:互联网 发布:linux if语句多个条件 编辑:程序博客网 时间:2024/05/16 14:55

环境

  • php5.6+
  • swoole扩展

需求

实现简单的广播, 支持身份验证

源码

废话少说,上代码.

<?php namespace church;use ReflectionClass;use ReflectionException;use Swoole\Websocket\Server;class WebSocket{    public $host;    public $port;    public $config;    public $beforeAuthCallback = '';    public $afterAuthCallback = '';    public $beforeSendMsgCallback = '';     public $afterSendMsgCallback = '';    public $authenticator = '';    public $customers = [];    protected $server;    public function __construct($host = '0.0.0.0', $port = 9501, $config = [])    {        $this->host = $host;        $this->port = $port;            $this->config = $config;        $this->init();    }     public function init()    {        $this->server = new Server($this->host, $this->port);        !empty($this->config) && $this->server->set($this->config);        $this->beforeSendMsgCallback = function() {};        $this->afterSendMsgCallback = function() {};        $this->beforeAuthCallback = function() {};        $this->afterAuthCallback = function() {};        $this->authenticator = function() {};        $this->bindEvents();    }    public function bindEvents()    {        $this->server->on('open', [$this, 'onOpen']);        $this->server->on('message', [$this, 'onMessage']);        $this->server->on('close', [$this, 'onClose']);    }    public function run()    {       $this->server->start();     }    public function onOpen(Server $server, $request)    {        call_user_func($this->beforeAuthCallback, $server, $request);        if (!$this->auth($request)) {            return;        }        $this->customers[] = $request->fd;        call_user_func($this->afterAuthCallback, $server, $request);    }    public function onMessage(Server $server, $frame)    {        call_user_func($this->beforeSendMsgCallback, $server, $frame);        $this->broadcast($frame->fd, $frame->data);        call_user_func($this->afterSendMsgCallback, $server, $frame);    }    public function onClose($ser, $fd)    {        $key = array_search($fd, $this->customers);        unset($this->customers[$key]);    }    public function __call($method, $params)    {        $class_name = get_class($this->server);        $class = new ReflectionClass($class_name);        try {            $class->getMethod($method);        } catch (ReflectionException $e) {            echo "Method $method is not exists\n";            return;        }        call_user_func_array([$this->server, $method], $params);    }    public function broadcast($fromUser, $messages)    {        $users = array_diff($this->customers, [$fromUser]);        foreach ($users as $user)        {            $this->server->push($user, $messages);        }    }    private function auth($request)    {        if (($result = call_user_func($this->authenticator, $request)) === false) {            $this->server->push($request->fd, "auth failed");            $this->server->close($request->fd);        }        return $result;    }}

使用实例

<?php require './vendor/autoload.php';use church\WebSocket;$server = new WebSocket('0.0.0.0', 9501, [    'daemonize' => 1,]);$server->authenticator = function($request) use ($server) {    $get = $request->get;    return empty($get) || ($get['access_token'] == 'access_token');};$server->afterAuthCallback = function($ser, $request) use ($server) {    $server->push($request->fd, "auth successful"); };$server->run();
php index.php  #就会以守护进程方式运行

客户端js代码:

var websocket = new WebSocket("ws://192.168.2.106:9501?access_token=access_token");websocket.onopen=function(evt) {};websocket.onmessage = function(evt) {    console.log(evt);};websocket.onclose = function(evt) {  console.log(evt);};

搭建过程非常方便。实现的比较简陋,但是可以满足一般的需求了。支持身份验证功能,验证不通过会自动踢掉。