วิธีการส่งข้อมูลไปยังลูกค้าเฉพาะใน 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
หากต้องการส่งข้อความให้กับลูกค้าในระบบอื่น สามารถดูที่ การส่งข้อความในโปรเจกต์อื่น