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