cydrickn / socketio
兼容socket.io的PHP Websocket服务器
Requires
- php: >=8.1
Requires (Dev)
- openswoole/ide-helper: ^4.11
README
兼容 socket.io 的PHP Websocket服务器
到目前为止,本包中的函数用法几乎与socket.io中的命名相同
安装
composer require cydrickn/socketio
然后在你的主PHP代码中添加
require __DIR__ . '/../vendor/autoload.php';
用法
初始化你的服务器
要初始化
$server = new \Cydrickn\SocketIO\Server([ 'host' => '0.0.0.0', 'port' => 8000, 'mode' => SWOOLE_PROCESS, 'settings' => [ \Swoole\Constant::OPTION_WORKER_NUM => swoole_cpu_num() * 2, \Swoole\Constant::OPTION_ENABLE_STATIC_HANDLER => true, ] ]); $server->on('Started', function (\Cydrickn\SocketIO\Server $server) { echo 'Websocket is now listening in ' . $server->getHost() . ':' . $server->getPort() . PHP_EOL; }); $server->on('connection', function (\Cydrickn\SocketIO\Socket $socket) { // ... }); $server->start();
服务器选项
服务器实例
这是服务器 \Cydrickn\SocketIO\Server,它也继承了所有 \Cydrickn\SocketIO\Socket 的方法
事件
基本 Emit
要发送,只需调用 \Cydrickn\SocketIO\Socket::emit
$server->on('connection', function (\Cydrickn\SocketIO\Socket $socket) { $socket->emit('hello', 'world'); });
你可以传递尽可能多的参数
$socket->emit('hello', 'world', 1, 2, 3, 'more');
不需要在对象/数组上运行 json_encode,因为它会为你完成。
// BAD $socket->emit('hi', json_encode(['name' => 'Juan'])); // GOOD $socket->emit('hi', ['name' => 'Juan']);
广播
广播就像简单的 emit 一样,但它将发送给除了当前客户端之外的所有连接客户端
$socket->broadcast()->emit('hi', ['name' => 'Juan']);
发送给所有客户端
toAll 将向所有连接的客户端发送消息,包括当前客户端
$socket->toAll()->emit('hi', ['name' => 'Juan']);
确认
与node.js的socket io相同,你只需在 emit 的最后一个参数中添加一个可调用的函数
服务器
$socket->emit('hi', function () { //... });
客户端
socket.on('hi', (callback) => { callback('hello'); });
带超时
为每个 emit 分配超时
// timeout for 5 seconds $socket->timeout(5000)->emit('hi', function (bool $err) { if ($err) { // the other side did not acknowledge the event in the given delay } });
为超时添加回调默认参数值
// timeout for 5 seconds $socket->timeout(5000, 'Juan')->emit('hi', function (bool $err, string $name) { var_dump($name); // if the other side did not acknowledge the event the $name will be 'Juan' if ($err) { // the other side did not acknowledge the event in the given delay } });
监听
监听任何事件
$server->on('hello', function (\Cydrickn\SocketIO\Socket $socket, string $world) { // ... }); $server->on('hi', function (\Cydrickn\SocketIO\Socket $socket, array $name) { // ... });
服务器事件
此事件不能用于路由,因为这是Swoole Websocket事件的所有事件,所有带有 * 的事件均不应使用
- 请求 - 当你用它用于http时
- *WorkerStart - 你必须不要替换此事件,因为这是此包的worker启动逻辑
- *Start - 你必须不要替换此事件,因为这是此包的启动逻辑
- *Open - 你必须不要替换此事件,因为这是此包的连接逻辑
- *Message - 你必须不要替换此事件,因为这是此包的消息逻辑
- *Close - 你必须不要替换此事件,因为这是此包的消息逻辑
房间
在这个包中已经包含了房间
要加入组,只需调用函数 join
$socket->join('room1');
要发送消息
$socket->to('room1')->emit('hi', ['name' => 'Juan']);
向多个房间发送消息
$socket->to('room1')->to('room2')->emit('hi', ['name' => 'Juan']);
离开房间
$socket->leave('room1');
向特定用户发送消息
在socket.iojavascript中,为每个客户端 sid 自动创建了一个新的房间
但当前在这个包中,它不会为每个客户端创建一个新的房间
在这个包中,你只需指定它是房间还是 sid
use Cydrickn\SocketIO\Message\Response; $socket->on('private message', (\Cydrickn\SocketIO\Socket $socket, $anotherSocketId, $msg) => { $socket->($anotherSocketId, Response::TO_TYPE_SID).emit('private message', $socket->sid, $msg); });
中间件
可以为服务器添加中间件
$server->use(function (\Cydrickn\SocketIO\Socket $socket, callable $next) { // ... $next(); });
要停止连接,只需在 $next 中传递 \Error
$server->use(function (\Cydrickn\SocketIO\Socket $socket, callable $next) { // ... $next(new \Error('Something went wrong')); });
你还可以为 Swoole Server 的握手事件添加中间件。只需将第二个参数传递为 true。
在回调中,它将传递响应供你修改(如果需要的话)
$server->use(function (\Cydrickn\SocketIO\Socket $socket, \Swoole\Http\Response $response, callable $next) { // ... }, true);
如果你想创建一个中间件类,我们建议实现 Cydrickn\SocketIO\Middleware\MiddlewareInterface
,如果用于握手,则使用 Cydrickn\SocketIO\Middleware\HandshakeMiddlewareInterface
用于握手的中间件示例是 Cydrickn\SocketIO\Middleware\CookieSessionMiddleware。此中间件将创建一个使用cookie的会话,如果客户端没有发送会话cookie,则它将创建一个cookie并将其作为握手响应发送。
会话
在这个包中已经存在可以使用的会话存储功能。
- SessionsTable - 使用 Swoole.Table 作为存储
- SessionsNative - 使用文件存储
在使用 Swoole 时,不应使用 session_start 和 $_SESSION,因为这两个函数是全局的,它们将数据存储在进程本身中。
这里提供的会话不使用预定义的会话扩展。目前,会话是按连接定义的,因此您可以通过以下方式获取会话。
$socket->getSession();
如果您的中间件没有创建会话,则 getSession 可能返回 null。
设置会话
$session = $server->getSessionStorage()->get('123456'); // This will automatically created once it does not exists $socket->setSession($session);
您也可以自定义会话存储,只需实现 Cydrickn\SocketIO\Session\SessionStorageInterface
<?php class CustomeStorage implements SessionStorageInterface { // ... }
创建您的存储后
您需要将其传递给您的服务器构造函数
$server = new \Cydrickn\SocketIO\Server([ 'host' => '0.0.0.0', 'port' => 8000, 'mode' => SWOOLE_PROCESS, 'serve_http' => true, 'settings' => [ \Swoole\Constant::OPTION_WORKER_NUM => swoole_cpu_num() * 2, \Swoole\Constant::OPTION_ENABLE_STATIC_HANDLER => true, \Swoole\Constant::OPTION_DOCUMENT_ROOT => dirname(__DIR__).'/examples' ] ], sessionStorage: new CustomeStorage());
示例
待办事项
- 离开房间
- 修复断开连接事件
- 发出确认
- 实现超时发出
- 实现全部监听器
- 实现 once、off、removeAllListeners