先上有问题的代码:
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";
}
}