Hyperf提供有直接从容器中获取SocketIO实例的方法:
$io = \Hyperf\Utils\ApplicationContext::getContainer()->get(\Hyperf\SocketIOServer\SocketIO::class); 那么另提供的有在短连接中有根据这个实例去把某个sid加入某个房间的功能吗?
现实业务中可能有这么一个场景:在短连接接口中创建房间,然后创建成功后自动把创建人加入到刚创建成功的房间内。
开始先想到客户端通过短连接成功创建房间后,把房间ID返回给客户端,然后客户端再调用socket长连接的加入房间接口自己主动发起加入房间,但这种方式有点不简洁,有没有更简洁直接的方式呢?
官方文档中有个$socket->join($data);这个是把当前socket的用户加入的某个房间,那么怎么在短连接中把某个用户,如uid值为2的,找到其fd值,然后把其加入某个房间呢?
首先在握手时的onOpen方法中增加一条:
$this->redis->hMSet("ws:user:{$uid}", ['uid' => $uid, 'fd' => $request->fd, 'sid' => $sid, 'ip' => $request->server['remote_addr']]);上面的方法是根据握手时客户端传递的用户信息及fd信息建立匹配对照关系。
然后在短连接控制器joinRoom演示样例中增加一个方法:
use Hyperf\Di\Annotation\Inject; use Hyperf\WebSocketServer\Sender; use Hyperf\SocketIOServer\Socket; use Hyperf\SocketIOServer\Collector\SocketIORouter; /** * @Inject() * @var Sender */ private $sender; public function joinRoom() { $container = ApplicationContext::getContainer(); $redis = $container->get(\Hyperf\Redis\Redis::class); $fd = (int)$redis->hGet("ws:user:2", 'fd'); Debug::create(['k' => 'fd', 'v' => $fd]); $socket = make(Socket::class, [ 'adapter' => SocketIORouter::getAdapter('/'), 'sender' => $this->sender, 'fd' => $fd, 'nsp' => '/', 'addCallback' => function (string $ackId, Channel $channel, ?int $timeout = null) { $this->addCallback($ackId, $channel, $timeout); }, ]); $room = '1'; $socket->join($room); // 向房间内其他用户推送(不含当前用户) $emitData = json_encode([ 'type' => 1, 'data' => ['fd' => $fd, 'time' => date('Y-m-d H:i:s'), 'msg' => "hello world:"] ]); $socket->to($room)->emit('event', $emitData); //给房间的其它人推送,除了自己 $socket->emit('event', $emitData); //给自己推送 return 'ligaofeng'; }