<?php
declare (strict_types=1);
namespace app\server;
use think\worker\Server;
use Workerman\Connection\TcpConnection;
class index extends Server
{
protected $protocol = 'websocket';
protected $host = '103.146.100.36';
protected $port = 2004;
// onConnect
public function onConnect(TcpConnection $connection)
{
dump('connect');
}
// onMessage (接收到数据)
public function onMessage(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 发送 message
// uid 为 all 时是全局广播
//explode通过:分割字符串,返回数组,list分配分割返回的数组。
list($recv_uid, $message) = explode(':', $data);
if ($recv_uid == 'all') {
// 全局广播
broadcast($message);
} else {
// 给特定uid发送
sendMessageByUid($recv_uid, $message);
}
}
// onClose (断开连接)
public function onClose(TcpConnection $connection)
{
global $worker;
if (isset($connection->uid)) {
// 连接断开时删除映射,通过key删除指定元素
unset($worker->uidConnections[$connection->uid]);
}
}
// onError (发生错误)
public function onError(TcpConnection $connection, $code, $msg)
{
dump("error [ $code ] $msg\n");
}
}
// 向所有验证的用户推送数据
function broadcast($message)
{
global $worker;
//遍历全局数组,然后发送数据
foreach ($worker->uidConnections as $connection) {
$connection->send($message);
}
}
// 针对uid推送数据
function sendMessageByUid($uid, $message)
{
global $worker;
//指定key,然后取出对应的value,然后发送数据
if (isset($worker->uidConnections[$uid])) {
$connection = $worker->uidConnections[$uid];
$connection->send($message);
}
}
THE END