服务端
use Workerman\Lib\Timer;
use Workerman\Worker;
require_once __DIR__ . '/../../vendor/autoload.php';
// 心跳间隔55秒
define('HEARTBEAT_TIME', 5500);
$worker = new Worker('websocket://0.0.0.0:1415');
$worker->count = 1;
$connections = []; //uid和connection绑定关系
$worker->onWorkerStart = function ($worker) {
Timer::add(1, function () use ($worker) {
$time_now = time();
foreach ($worker->connections as $connection) {
// 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间
if (empty($connection->lastMessageTime)) {
$connection->lastMessageTime = $time_now;
continue;
}
// 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接
if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) {
$connection->close();
}
}
});
$inner_text_worker = new Worker('text://127.0.0.1:5678');
//这里的$connection是给推送者调用的
$inner_text_worker->onMessage = function ($connection, $buffer) {
$data = json_decode($buffer, true);
$uid = $data['uid'];
// 通过workerman,向uid的页面推送数据
$ret = sendMessageByUid($uid, $data['msg']);
// 返回推送结果
$connection->send($ret ? 'ok' : 'fail');
};
$inner_text_worker->listen();
};
//连接上立马发送一个init包,绑定uid和connection
$worker->onMessage = function ($connection, $data) {
global $worker;
$connection->lastMessageTime = time();
$json = json_decode($data, true);
if ($json['type'] == 'init') {
bindUidConnection($json['uid'], $connection);
$connection->uid = $json['uid'];
$connection->send("绑定成功");
} else {
$connection->send("ping");
}
};
$worker->onClose = function ($connection) {
global $worker;
global $connections;
if (isset($connection->uid)) {
// 连接断开时删除映射
unset($connections[$connection->uid]);
}
};
function bindUidConnection($uid, $connection)
{
global $connections;
if (!isset($connections[$uid])) {
$connections[$uid] = $connection;
}
}
function sendMessageByUid($uid, $message)
{
global $worker;
global $connections;
if (isset($connections[$uid])) {
$connection = $connections[$uid];
$connection->send($message);
return true;
}
return false;
}
Worker::runAll();
推送端
$client = stream_socket_client('tcp://127.0.0.1:5678', $errno, $errmsg, 1);
print_r($client);
// 推送的数据,包含uid字段,表示是给这个uid推送
$data = array('uid' => 100, 'msg' => '你好');
// 发送数据,注意5678端口是Text协议的端口,Text协议需要在数据末尾加上换行符
fwrite($client, json_encode($data) . "\n");
// 读取推送结果
echo "推送消息\n";
echo fread($client, 8192);
Client
使用的是在线工具: