Workerman에서 특정 클라이언트에게 데이터를 전송하는 방법

worker를 사용하여 서버를 구축하고 GatewayWorker를 사용하지 않고, 특정 사용자에게 메시지를 푸시하려면 어떻게 해야 하나요?

<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';

// 1234 포트를 청취하는 worker 컨테이너 초기화
$worker = new Worker('websocket://workerman.net:1234');
// ====여기서 프로세스 수는 반드시 1로 설정해야 함====
$worker->count = 1;
// uid와 connection의 매핑을 저장하기 위한 새 속성 추가(uid는 사용자 id 또는 클라이언트의 고유 식별자)
$worker->uidConnections = array();
// 클라이언트가 메시지를 보낼 때 실행되는 콜백 함수
$worker->onMessage = function(TcpConnection $connection, $data)
{
    global $worker;
    // 현재 클라이언트가 인증되었는지 여부 확인, 즉 uid가 설정되었는지 확인
    if(!isset($connection->uid))
    {
       // 인증되지 않은 경우 첫 번째 패킷을 uid로 간주(여기서는 편리한 시연을 위해 실제 인증을 수행하지 않음)
       $connection->uid = $data;
       /* uid와 connection의 매핑을 저장, 이를 통해 uid로 connection을 쉽게 조회할 수 있어,
        * 특정 uid로 데이터 푸시를 구현 가능
        */
       $worker->uidConnections[$connection->uid] = $connection;
       return $connection->send('login success, your uid is ' . $connection->uid);
    }
    // 기타 로직, 특정 uid에 대해 전송 또는 전역 방송
    // 메시지 형식이 uid:message일 때 uid에 메시지를 전송
    // uid가 all일 때는 전역 방송
    list($recv_uid, $message) = explode(':', $data);
    // 전역 방송
    if($recv_uid == 'all')
    {
        broadcast($message);
    }
    // 특정 uid에 전송
    else
    {
        sendMessageByUid($recv_uid, $message);
    }
};

// 클라이언트 연결이 끊어질 때
$worker->onClose = function(TcpConnection $connection)
{
    global $worker;
    if(isset($connection->uid))
    {
        // 연결이 끊어지면 매핑 삭제
        unset($worker->uidConnections[$connection->uid]);
    }
};

// 모든 인증된 사용자에게 데이터 푸시
function broadcast($message)
{
   global $worker;
   foreach($worker->uidConnections as $connection)
   {
        $connection->send($message);
   }
}

// uid에 대해 데이터 푸시
function sendMessageByUid($uid, $message)
{
    global $worker;
    if(isset($worker->uidConnections[$uid]))
    {
        $connection = $worker->uidConnections[$uid];
        $connection->send($message);
    }
}

// 모든 worker 실행 (사실 현재 하나만 정의됨)
Worker::runAll();

설명:

위 예제는 uid에 대해 푸시할 수 있으며, 단일 프로세스이지만 10만 명의 온라인을 지원하는 데는 문제가 없습니다.

주의: 이 예제는 반드시 단일 프로세스여야 하며, 즉 $worker->count는 1이어야 합니다. 다중 프로세스 또는 서버 클러스터를 지원하려면 Channel 구성 요소를 사용하여 프로세스 간 통신을 수행해야 하며, 개발도 매우 간단합니다. Channel 구성 요소 클러스터 푸시 예제 섹션을 참조할 수 있습니다.

다른 시스템에서 클라이언트에게 메시지를 푸시하려는 경우 다른 프로젝트에서 푸시 섹션을 참조하십시오.