准备工作:
需要已搭建好workerman并能连接正常fastadmin安装Workerman-优快云博客
Worker.php代码
<?php
namespace app\push\controller;
use think\Db;
use think\worker\Server;
use Workerman\Lib\Timer;
class Worker extends Server
{
protected $socket = 'websocket://0.0.0.0:2346';
protected $heartbeat_time = '55';
/**
* 收到信息
* @param $connection
* @param $data
*/
public function onMessage($connection, $datas)
{
$connection->lastMessageTime = time();
$data = json_decode($datas,true);
switch ($data['type']) {
case 'login':
/*登录逻辑*/
$user = Db::name('user')->where(['id'=>$data['user_id']])->find();
if (!$user) {
$connection->send('参数错误');
}else{
Db::name('user')->where('id',$data['user_id'])->update(['on_line'=>1,'logintime'=>time()]);
$connection->user_id = $data['user_id'];
$connection->send('用户'.$user['nickname'].'登录成功');
}
break;
/*长联心跳*/
case 'ping':
// $connection->send('ping');
break;
/*预约*/
case 'eservation':
if (empty($data['send_uid'])){
$send_uid = [];
}else{
$send_uid = explode(',',$data['send_uid']);
}
$mgs = '这是一个推送消息';
$this->pushMessage($mgs,$send_uid);
break;
}
}
/**
* 当连接建立时触发的回调函数
* @param $connection
*/
public function onConnect($connection)
{
$connection->send('连接成功');
}
/**
* 当连接断开时触发的回调函数
* @param $connection
*/
public function onClose($connection)
{
if (!empty($connection->user_id)){
Db::name('user')->where('id',$connection->user_id)->update(['on_line'=>0,'updatetime'=>time()]);
}
$connection->send('close');
}
/**
* 当客户端的连接上发生错误时触发
* @param $connection
* @param $code
* @param $msg
*/
public function onError($connection, $code, $msg)
{
echo "error $code $msg\n";
}
/**
* 每个进程启动
* @param $worker
*/
public function onWorkerStart($worker)
{
Timer::add(10, function () use ($worker) {
$time_now = time();
foreach ($worker->connections as $connection) {
// 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间
if (empty($connection->lastMessageTime)) {
$connection->lastMessageTime = $time_now;
continue;
}
// $diff_time = $time_now - $connection->lastMessageTime;
// $msg = '距离上次通话已经过去' . $diff_time . '秒';
// $connection->send($msg);
// 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接
if ($time_now - $connection->lastMessageTime > $this->heartbeat_time) {
$connection->close();
}
}
});
}
/**
* 给指定id推送消息[1,2,3,4]
* @param $message
* @param $userIds
*/
public function pushMessage($message, $userIds = null)
{
if (empty($userIds)) {
foreach ($this->worker->connections as $connection) {
$connection->send($message);
}
} else {
foreach ($this->worker->connections as $connection) {
if (in_array($connection->user_id, $userIds)) {
$connection->send($message);
}
}
}
}
}
在测试工具中websocket/ws/wss在线调试测试工具,用多个窗口模拟已登录的状态
用户1
用户2
用户3
发送json数据到服务器
{"type":"login","user_id":"2,3"}