继承swoole_websocket_server类使用on方法时候需要注意的地方

147 阅读2分钟

先上有问题的代码:

class Server extends \swoole_websocket_server
{
    public function __construct($ip, $port)
    {
        parent::__construct($ip, $port);
        $this->init();
    }
 
    protected function init()
    {
        $this->on('open', [$this, '__open']);
        $this->on('message', [$this, '__message']);
        $this->on('close', [$this, '__close']);
    }
 
    protected function __open($server, $request)
    {
        echo "server: handshake success with fd{$request->fd}\n";
    }
     
    protected function __message($server, $frame)
    {
        echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
        $this->push($frame->fd, "this is server");
    }
 
    protected function __close($server, $fd)
    {
        echo "client {$fd} closed\n";
    }
}
运行时候,onclose那一行报错,而open和message没毛病。

我上github提了issue,后来韩天峰大神回答了原因。

请所有事件回到设置为public


虽然另外两个事件回调设置成功了,但是这只是绕开了swoole_websocekt_server::on方法的检测,在回调这些函数时仍然可能遇到作用域的问题。


__close设置未成功是因为需要调用swoole_server_port::on方法将回调函数设置到监听端口上,这个类和swoole_websocekt_server没有任何继承关系。

下面给出两种解决方法。

方法一

将所有方法改为public,妥妥的,最方便。但是有强迫症患者,可能不舒服。
class Server extends \swoole_websocket_server
{
    public function __construct($ip, $port)
    {
        parent::__construct($ip, $port);
        $this->init();
    }
 
    protected function init()
    {
        $this->on('open', [$this, '__open']);
        $this->on('message', [$this, '__message']);
        $this->on('close', [$this, '__close']);
    }
 
    public function __open($server, $request)
    {
        echo "server: handshake success with fd{$request->fd}\n";
    }
     
    public function __message($server, $frame)
    {
        echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
        $this->push($frame->fd, "this is server");
    }
 
    public function __close($server, $fd)
    {
        echo "client {$fd} closed\n";
    }
}

方法二

通过闭包,在闭包里调用方法。性能上多一次方法调用,可能略差,但是强迫症患者喜欢啊!
class Server extends \swoole_websocket_server
{
    public function __construct($ip, $port)
    {
        parent::__construct($ip, $port);
        $this->init();
    }
 
    protected function init()
    {
        $this->on('open', function($server, $request){
            $this->__open($server, $request);
        });
        $this->on('message', function($server, $frame){
            $this->__message($server, $frame);
        });
        $this->on('close', function($server, $fd){
            $this->__close($server, $fd);
        });
    }
 
    protected function __open($server, $request)
    {
        echo "server: handshake success with fd{$request->fd}\n";
    }
     
    protected function __message($server, $frame)
    {
        echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
        $this->push($frame->fd, "this is server");
    }
 
    protected function __close($server, $fd)
    {
        echo "client {$fd} closed\n";
    }
}