使用SwooleTable

1.定义Table,支持定义多个Table。

Swoole启动之前会创建定义的所有Table。

  1. // 在"config/laravels.php"配置
  2. [
  3. // ...
  4. 'swoole_tables' => [
  5. // 场景:WebSocket中UserId与FD绑定
  6. 'ws' => [// Key为Table名称,使用时会自动添加Table后缀,避免重名。这里定义名为wsTable的Table
  7. 'size' => 102400,//Table的最大行数
  8. 'column' => [// Table的列定义
  9. ['name' => 'value', 'type' => \Swoole\Table::TYPE_INT, 'size' => 8],
  10. ],
  11. ],
  12. //...继续定义其他Table
  13. ],
  14. // ...
  15. ];

2.访问Table:所有的Table实例均绑定在SwooleServer上,通过app('swoole')->xxxTable访问。

  1. namespace App\Services;
  2. use Hhxsv5\LaravelS\Swoole\WebSocketHandlerInterface;
  3. use Swoole\Http\Request;
  4. use Swoole\WebSocket\Frame;
  5. use Swoole\WebSocket\Server;
  6. class WebSocketService implements WebSocketHandlerInterface
  7. {
  8. /**@var \Swoole\Table $wsTable */
  9. private $wsTable;
  10. public function __construct()
  11. {
  12. $this->wsTable = app('swoole')->wsTable;
  13. }
  14. // 场景:WebSocket中UserId与FD绑定
  15. public function onOpen(Server $server, Request $request)
  16. {
  17. // var_dump(app('swoole') === $server);// 同一实例
  18. /**
  19. * 获取当前登录的用户
  20. * 此特性要求建立WebSocket连接的路径要经过Authenticate之类的中间件。
  21. * 例如:
  22. * 浏览器端:var ws = new WebSocket("ws://127.0.0.1:5200/ws");
  23. * 那么Laravel中/ws路由就需要加上类似Authenticate的中间件。
  24. * Route::get('/ws', function () {
  25. * // 响应状态码200的任意内容
  26. * return 'websocket';
  27. * })->middleware(['auth']);
  28. */
  29. // $user = Auth::user();
  30. // $userId = $user ? $user->id : 0; // 0 表示未登录的访客用户
  31. $userId = mt_rand(1000, 10000);
  32. // if (!$userId) {
  33. // // 未登录用户直接断开连接
  34. // $server->disconnect($request->fd);
  35. // return;
  36. // }
  37. $this->wsTable->set('uid:' . $userId, ['value' => $request->fd]);// 绑定uid到fd的映射
  38. $this->wsTable->set('fd:' . $request->fd, ['value' => $userId]);// 绑定fd到uid的映射
  39. $server->push($request->fd, "Welcome to LaravelS #{$request->fd}");
  40. }
  41. public function onMessage(Server $server, Frame $frame)
  42. {
  43. // 广播
  44. foreach ($this->wsTable as $key => $row) {
  45. if (strpos($key, 'uid:') === 0 && $server->isEstablished($row['value'])) {
  46. $content = sprintf('Broadcast: new message "%s" from #%d', $frame->data, $frame->fd);
  47. $server->push($row['value'], $content);
  48. }
  49. }
  50. }
  51. public function onClose(Server $server, $fd, $reactorId)
  52. {
  53. $uid = $this->wsTable->get('fd:' . $fd);
  54. if ($uid !== false) {
  55. $this->wsTable->del('uid:' . $uid['value']); // 解绑uid映射
  56. }
  57. $this->wsTable->del('fd:' . $fd);// 解绑fd映射
  58. $server->push($fd, "Goodbye #{$fd}");
  59. }
  60. }