1、创建项目
composer create-project workerman/webman
2、给webman安装GatewayWorker插件
(1)进入webman目录
cd webman
(2)执行
composer require webman/gateway-worker
3、配置及业务目录
配置文件在 config/plugin/webman/gateway-worker/
目录
业务目录在 plugin/webman/gateway
目录
4、安装 redis 扩展
(1)安装
composer require psr/container ^1.1.1 illuminate/redis illuminate/events
(2)配置
redis配置文件在 config/redis.php
return [
'default' => [
'host' => '127.0.0.1',
'password' => null,
'port' => 6379,
'database' => 0,
]
];
例如:
在 app/controller/
目录下创建 IndexController
控制器文件(webman默认创建),代码如下:
namespace app\controller;
use GatewayWorker\Lib\Gateway;
class IndexController
{
/**
* 绑定关系:
* 将client_id与uid绑定,以便通过Gateway::sendToUid($uid)发送数据,
* 通过Gateway::isUidOnline($uid)用户是否在线。
* uid解释:这里uid泛指用户id或者设备id,用来唯一确定一个客户端用户或者设备。
*/
public function bind()
{
$clientId = "7f00000108fc00000001";
$data = [
'type' => 'login',
'uid' => 1,
];
Gateway::bindUid($clientId, $data['uid']);
Gateway::sendToClient($clientId, '已成功绑定');
}
/**
* 查看用户是否在线
* isOnline()方法:在线返回1,不在线返回0
*/
public function online()
{
if (Gateway::isUidOnline(1)) {
print_r('在线');
} else {
print_r('不在线');
}
}
}
修改 plugin/webman/gateway
目录中的 Events.php
代码如下:
namespace plugin\webman\gateway;
use GatewayWorker\Lib\Gateway;
use support\Redis;
class Events
{
public static function onWorkerStart($worker)
{
}
// 连接上gateway进程时触发的回调函数
public static function onConnect($client_id)
{
// 在线人数 +1
Redis::incr('user_online_number:');
// 向当前客户端连接发送消息,如果前端收到了表示连接成功了
Gateway::sendToCurrentClient("Your client_id is $client_id");
}
public static function onWebSocketConnect($client_id, $data)
{
}
public static function onMessage($client_id, $message)
{
}
// 客户端与Gateway进程的连接断开时触发
public static function onClose($client_id)
{
// 在线人数 -1
Redis::decr('user_online_number:');
}
}
以上步骤完成后,我们运行一下:
进入webman
目录
(1)debug
方式运行(用于开发调试)
php start.php start
(2)daemon方式运行(用于正式环境)
php start.php start -d
(3)windows用户:双击windows.bat 或者运行 php windows.php 启动
运行后截图如下(我在windows环境):
可以看到成功运行起来了,这时候我们去创建 html 文件进行测试。
1、创建 html 文件
doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
head>
<body>
<script>
ws = new WebSocket("ws://127.0.0.1:7272");
ws.onopen = function () {
console.log("连接成功")
ws.send("你好")
}
ws.onmessage = function(e){
console.log("收到一条新消息:" + e.data)
};
ws.onclose = function(){
console.log("已关闭")
};
script>
body>
html>
2、在浏览器中打开
打开控制台查看,可以看到连接成功,并且 onConnect
回调函数返回了当前用户的 client_id
:7f00000108fc00000001
通过 redis 工具可以看到用户连接成功后,在线人数增加了1
这时候我们再多打开几个标签,看下是否增加
可以看到值跟随着标签的打开而增加,三个标签相当于三个用户同时在线
如果此时关闭其中一个标签,相当于其中一个用户下线了,那值也会相应的减少1
之前在控制器中我们创建了两个方法:bind(绑定用户)、online(查询用户是否在线)
1、bind(绑定用户)
该方法一般用于用户登录成功后,将前端传过来的 client_id
与用户的 UID 进行一个绑定操作,以便于后续我们可以通过 client_id
知道这个用户是否在线或者是给用户发送消息。
请求接口:
http://127.0.0.1:8787/index/bind
在控制台中可以看到服务端返回成功绑定的消息,此时 7f00000108fc00000001 与 uid 为1的用户已成功绑定
2、online(用户在线状态)
该方法一般用于用户前端显示用户在线的状态,或者是给用户推送消息时的提前判断
请求接口:
http://127.0.0.1:8787/index/online
可以看到用户的在线状态
如果此时我关闭了用户 1 的网页标签,再次请求接口,此时可以看到用户变成了离线状态
uid在线返回1,不在线返回0
注意:如果是客户端断网断电等极端情况掉线,客户端的onClose回调可能无法及时触发,参见onClose说明。也就是说对应客户端出现断网断电等极端掉线情况返回值可能是1,而并非期待的0。这种情况需要心跳来检测已经掉线的客户端。