您现在的位置是:首页> 编程文章 个人博客模板
laravel5.8 使用 workerman搭建聊天系统
无痕小Q个人博客 2021-04-20 10:40:33【 主页】 774人已围观
简介laravel5.8 使用 workerman搭建聊天系统
laravel5.8 使用 workerman搭建聊天系统
1:laravel安装workman
composer require workerman/workerman
2:创建命令类,启停workman
php artisan make:command Workerman
3:执行该命令会在 app/Console/Commands/
下面创建 Workerman.php
文件,该文件代码如下:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Workerman\Autoloader;
use Workerman\Worker;
class Workerman extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'Workerman {action} {--daemonize}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'workerman 启动停止';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
global $argv;//定义全局变量
$arg = $this->argument('action');
$argv[1] = $arg;
$argv[2] = $this->option('daemonize') ? '-d' : '';//该参数是以daemon(守护进程)方式启动
global $text_worker;
// 创建一个Worker监听2345端口,使用websocket协议通讯
$text_worker = new Worker("websocket://0.0.0.0:2345");
$text_worker->uidConnections = array();//在线用户连接对象
$text_worker->uidInfo = array();//在线用户的用户信息
// 启动4个进程对外提供服务
$text_worker->count = 4;
//引用类文件
$handler = \App::make('Handler\WorkermanHandler');
$text_worker->onConnect = array($handler,"handle_connection");
$text_worker->onMessage = array($handler,"handle_message");
$text_worker->onClose = array($handler,"handle_close");
$text_worker->onWorkerStart = array($handler,"handle_start");
// 运行worker
Worker::runAll();
}
}
注意:action 是启动参数,daemonize选项是是否后台运行,如果不需要后台运行请把有关daemonize的代码删掉。 最最重要的地方来了$argv一定不能删掉,否则启动workerman的时候会报错
3:
app/Handler/WorkermanHandler.php
<?php
namespace Handler;
use Illuminate\Console\Command;
use Workerman\Lib\Timer;
use Workerman\Worker;
class WorkermanHandler
{
private $heartbeat_time = 55;//心跳间隔55秒
//当客户端连上来时分配uid,并保存链接,并通知所有客户端
public function handle_connection($connection){
global $text_worker;
//判断是否设置了UID
if(!isset($connection->uid)){
//给用户分配一个UID
// $connection->uid = random_string(20);
$connection->uid = $this->str_rand(10);
//保存用户的uid
$text_worker->uidConnections["{$connection->uid}"] = $connection;
//向用户返回创建成功的信息
$connection->send("用户:[{$connection->uid}] 创建成功");
}
}
public function handle_start(){
global $text_worker;
//每秒都判断客户端是否已下线
Timer::add(1, function()use($text_worker){
$time_now = time();
foreach($text_worker->connections as $connection) {
// 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间
if (empty($connection->lastMessageTime)) {
$connection->lastMessageTime = $time_now;
continue;
}
// 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接
if ($time_now - $connection->lastMessageTime > $this->heartbeat_time) {
// $connection->close();
}
}
});
//每隔30秒就向客户端发送一条心跳验证
Timer::add(1,function ()use ($text_worker){
foreach ($text_worker->connections as $conn){
$msg = [
'type' => 'ping',
'msg' => '心跳验证',
'time' => date('Y-m-d H:i:s')
];
$conn->send(json_encode($msg));
}
});
}
//当客户端发送消息过来时,转发给所有人
public function handle_message($connection,$data){
global $text_worker;
//debug
//echo "data_info:".$data.PHP_EOL;
$connection->lastMessageTime = time();
$data_info=json_decode($data,true);
if(!$data_info){
return ;
}
//判断业务类型
switch($data_info['type'])
{
case 'login':
//判断用户信息是否存在
if(empty($data_info['user_id'])){
$connection->send("{'type':'error','msg':'非法请求'}");
return $connection->close();
}
//判断用户是否已经登录了
$user_ids=array_column($text_worker->uidInfo,"user_id");
if(in_array($data_info['user_id'],$user_ids)){
$connection->send("{'type':'error','msg':'你在其它地方已登录'}");
return $connection->close();
}
//存储用户信息
$text_worker->uidInfo["{$connection->uid}"]=array(
"user_id"=>$data_info['user_id'],
"user_name"=>htmlspecialchars($data_info['user_name']),
"user_header"=>$data_info['user_header'],
"create_time"=>date("Y-m-d H:i"),
);
//返回数据
if($data_info['to_uid'] == "all"){
$return_data=array(
"type"=>"login",
"uid"=>$connection->uid,
"user_name"=>htmlspecialchars($data_info['user_name']),
"user_header"=>$data_info['user_header'],
"send_time"=>date("Y-m-d H:i",time()),
"user_lists"=>$text_worker->uidInfo
);
$curral_data=array(
"type"=>"login_uid",
"uid"=>$connection->uid,
);
$connection->send(json_encode($curral_data));
//给所有用户发送一条数据
foreach($text_worker->connections as $conn){
$conn->send(json_encode($return_data));
}
}else{
return ;
}
return;
//用户发消息
case 'say':
if(!isset($text_worker->uidInfo["{$connection->uid}"]) || empty($text_worker->uidInfo["{$connection->uid}"])){
$connection->send('{"type":"error","msg":"你已经掉线了"}');
}
//获取到当前用户的信息
$user_info=$text_worker->uidInfo["{$connection->uid}"];
//判断是私聊还是群聊
if($data_info['to_uid'] != "all"){
//私聊
$return_data=array(
"type"=>"say",
"from_uid"=>$connection->uid,
"from_user_name"=>$user_info['user_name'],
"from_user_header"=>$user_info['user_header'],
"to_uid"=>$data_info['to_uid'],
"content"=>nl2br(htmlspecialchars($data_info['content'])),
"send_time"=>date("Y-m-d H:i")
);
if($data_info['to_uid'] == $connection->uid){
$connection->send(json_encode($return_data));
return;
}
//判断用户是否存在,并向对方发送数据
if(isset($text_worker->uidConnections["{$data_info['to_uid']}"])){
$to_connection=$text_worker->uidConnections["{$data_info['to_uid']}"];
$to_connection->send(json_encode($return_data));
}
//向你自己发送一条数据
$connection->send(json_encode($return_data));
}else{
//群聊
$return_data=array(
"type"=>"say",
"from_uid"=>$connection->uid,
"from_user_name"=>$user_info['user_name'],
"from_user_header"=>$user_info['user_header'],
"to_uid"=>"all",
"content"=>nl2br(htmlspecialchars($data_info['content'])),
"send_time"=>date("Y-m-d H:i")
);
//向所有用户发送数据
foreach($text_worker->connections as $conn){
$conn->send(json_encode($return_data));
}
}
return;
case "pong":
return;
}
}
/*
* 生成随机字符串
* @param int $length 生成随机字符串的长度
* @param string $char 组成随机字符串的字符串
* @return string $string 生成的随机字符串
*/
public function str_rand($length = 32) {
$char = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
if(!is_int($length) || $length < 0) {
return false;
}
$string = '';
for($i = $length; $i > 0; $i--) {
$string .= $char[mt_rand(0, strlen($char) - 1)];
}
return $string;
}
//当客户端断开时,广播给所有客户端
public function handle_close($connection){
global $text_worker;
$user_name=$text_worker->uidInfo[$connection->uid]['user_name'] ?? "";
unset($text_worker->uidConnections["{$connection->uid}"]);
unset($text_worker->uidInfo["{$connection->uid}"]);
if(!empty($user_name)){
$return_data=array(
"type"=>"logout",
"uid"=>$connection->uid,
"user_name"=>$user_name,
"create_time"=>date("Y-m-d H:i:s"),
);
foreach($text_worker->connections as $conn){
$conn->send(json_encode($return_data));
}
}
}
}
4:
composer.json
"app/Handler"
"autoload": {
"psr-4": {
"App\\": "app/"
},
"classmap": [
"database/seeds",
"database/factories",
"app/Handler"
]
},
5:
composer dump-autoload
6:执行命令启动 workerman
php artisan Workerman start --daemonize
7:客户端连接
阅读量! (774)
点击排行
网站公告
- 欢迎来到我的博客
1:欢迎来到我的博客
2:博客免费api接口现已上线
3:博客会定期更新文章
4:欢迎大家来捧场
站点信息
- 建站时间:2019-8-30
- 网站程序:php,laravel-swoole框架
- 今日流量:71(10分钟统计一次)
- 本月流量:9412
- 浏览总量:388339
- 统计方式:中间件,redis消息队列,定时任务