วิธีการส่งข้อมูลไปยังลูกค้าเฉพาะใน Workerman

ใช้ worker เพื่อทำเซิร์ฟเวอร์โดยไม่ใช้ GatewayWorker จะทำอย่างไรในการส่งข้อความไปยังผู้ใช้ที่กำหนด?

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

// เริ่มต้น worker container ที่ฟังพอร์ต 1234
$worker = new Worker('websocket://workerman.net:1234');
// ====จำนวนกระบวนการต้องตั้งค่าให้เป็น 1====
$worker->count = 1;
// เพิ่มคุณสมบัติใหม่เพื่อเก็บ uid กับการเชื่อมต่อ
$worker->uidConnections = array();
// ฟังก์ชัน callback ที่ทำงานเมื่อมีลูกค้าส่งข้อความเข้ามา
$worker->onMessage = function(TcpConnection $connection, $data)
{
    global $worker;
    // ตรวจสอบว่าลูกค้าปัจจุบันได้รับการตรวจสอบหรือไม่ นั่นคือมีการตั้งค่า uid หรือไม่
    if(!isset($connection->uid))
    {
       // หากยังไม่ตรวจสอบ จะใช้แพ็กเกจแรกเป็น uid (ที่นี่เพื่อความสะดวก ไม่มีการตรวจสอบจริง)
       $connection->uid = $data;
       /* บันทึก uid ไปยังการเชื่อมต่อ เพื่อให้สามารถค้นหาการเชื่อมต่อได้ง่ายๆ ผ่าน uid
        * เพื่อให้สามารถส่งข้อมูลไปยัง uid ที่เฉพาะเจาะจงได้
        */
       $worker->uidConnections[$connection->uid] = $connection;
       return $connection->send('login success, your uid is ' . $connection->uid);
    }
    // โลจิกอื่นๆ ส่งไปยัง uid ที่เฉพาะเจาะจงหรือกระจายข่าวสารทั่ว
    // สมมติว่า รูปแบบข้อความคือ uid:message เมื่อเป็นการส่ง 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 ได้ แม้ว่าจะเป็นกระบวนการเดียวแต่ก็รองรับผู้ใช้ออนไลน์ประมาณ 10W ได้ไม่มีปัญหา

หมายเหตุ ตัวอย่างนี้สามารถทำงานได้เฉพาะในกระบวนการเดียวเท่านั้น นั่นคือ $worker->count ต้องเป็น 1 หากต้องการสนับสนุนหลายกระบวนการหรือเซิร์ฟเวอร์คลัสเตอร์ จำเป็นต้องใช้ Channel component เพื่อทำการสื่อสารระหว่างกระบวนการ การพัฒนาไม่ยากสามารถดูได้ที่ ตัวอย่างการกระจายข้อมูลด้วย Channel component

หากต้องการส่งข้อความให้กับลูกค้าในระบบอื่น สามารถดูที่ การส่งข้อความในโปรเจกต์อื่น