测试工具  http://www.blue-zero.com/WebSocket/

2018年8月6日17:28:24

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Workerman\Worker;
use App\Work\ChatroomWork; class Chatroom extends Command { protected $taskserver;
/*
* 操作参数
* 注意只能在
* start 启动
* stop 停止
* relaod 只能重启逻辑代码,核心workerman_init无法重启,注意看官方文档
* status 查看状态
* connections 查看连接状态(需要Workerman版本>=3.5.0)
*
* 库 composer require workerman/workerman
*/
protected $action = array('start', 'stop', 'reload', 'status', 'connections'); /**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'Chatroom {action}'; /**
* The console command description.
*
* @var string
*/
protected $description = 'Chatroom'; /**
* Create a new command instance.
*
* @return void
*/
public function __construct() {
parent::__construct();
} /**
* Execute the console command.
*
* @return mixed
*
* 注意上线提供的方法
*
*/
public function handle() {
$action = $this->argument('action'); if (!in_array($action, $this->action)) {
$this->error('Error Action');
exit;
}
//初始化workerman
ChatroomWork::workerman_init($action);
} }
<?php

namespace App\Work;

use App\Work\BaseWork as Base;
use Illuminate\Support\Facades\DB;
use App\Work\CommonWork;
use Workerman\Worker;
use Workerman\Lib\Timer;
use App\Models\OperationLog;
use App\Models\Users; class ChatroomWork extends Base { //全局的总连接数
static $connection_count = 0;
//单个房间最大的连接数
static $room_max_numbers;
//房间所有的用户连接数ID集合,判断发送给那些用户,绑定用户和connection_id
static $room_connection_array = []; public static function workerman_init($action = null) {
global $argv; $argv[0] = 'workerman:websocket';
$argv[1] = $action;
// $argv[2] = '-d';
// 心跳
define('HEARTBEAT_TIME', 30);
//初始化
$worker = new Worker("websocket://172.17.1.247:9090");
$worker->name = 'Chatroom';
//linux 用户线上是www
// $worker->user = 'www';
//守护模式信息输出文件地址
// $worker->stdoutFile = "./workerman.log";
//工作进程总数 测试环境4个
$worker->count = 4;
//正式环境
// $ws->count = 10;
//建立链接 处理逻辑
$worker->onConnect = function($connection) {
// 有新的客户端连接时,连接数+1
self::$connection_count++;
self::onConnect($connection);
};
//接受消息 处理逻辑
$worker->onMessage = function($connection, $data) { self::onMessage($connection, $data);
};
//关闭链接 处理逻辑
$worker->onClose = function($connection) {
// 客户端关闭时,连接数-1
self::$connection_count--;
self::onClose($connection);
}; // 进程启动后设置一个30秒运行一次的定时器
$worker->onWorkerStart = function($worker) {
// Timer::add(1, function()use($worker) {
// $time_now = time();
// foreach ($worker->connections as $connection) {
//
// }
// });
};
// 开始
Worker::runAll();
} //建立链接 处理逻辑
public static function onConnect($connection) {
//主动心跳ping测试60秒一次
// Timer::add(HEARTBEAT_TIME, function() use($connection) {
// $connection->send(json_encode(['code' => 200, 'msg' => '服务存活', 'data' => [], 'connections' => self::$connection_count]));
// });
} //接受消息 处理逻辑
public static function onMessage($connection, $data) {
//解析数据,非合法的json数据不处理 if (!empty($data)) {
if (is_json($data)) {
$data = json_decode($data, true); if ($data['action_type'] == 'ping') {
// 客户端回应服务端的心跳
$connection->send(json_encode(['code' => 200, 'msg' => '服务存活', 'data' => [], 'connections' => self::$connection_count]));
} elseif ($data['action_type'] == 'login') {
//用户登录
if ($data['is_login'] == 1) {
//匿名登录
self::$room_connection_array[$data['room_id']][$connection->id]['user_name'] = '匿名用户' . $connection->id; $connection->send(json_encode(['code' => 200, 'msg' => '匿名登录成功', 'data' => self::$room_connection_array, 'connections' => self::$connection_count]));
} elseif ($data['is_login'] == 2) {
//已登录
$Users = Users::where('id', $data['user_id'])->first();
if (empty($Users)) {
$connection->send(json_encode(['code' => 201, 'msg' => '用户ID无效或者错误', 'data' => [], 'connections' => self::$connection_count]));
} else {
$Users = $Users->toArray();
self::$room_connection_array[$data['room_id']][$connection->id]['user_name'] = empty($Users['realname']) ? $data['user_id'] : $Users['realname']; $connection->send(json_encode(['code' => 200, 'msg' => '登录成功', 'data' => self::$room_connection_array, 'connections' => self::$connection_count]));
}
} else {
$connection->send(json_encode(['code' => 201, 'msg' => '登录类型数据错误', 'data' => [], 'connections' => self::$connection_count]));
}
} elseif ($data['action_type'] == 'broadcast_to_all') {
//只发给房间的所有的人,除去自己
foreach ($connection->worker->connections as $con) {
foreach (self::$room_connection_array[$data['room_id']] as $k => $v) {
// p($con->id);
// p($k);
if ($k == $con->id && $con->id != $connection->id) {
$con->send($data['message']);
}
}
}
} elseif ($data['action_type'] == 'broadcast_to_one') { } else {
$connection->send(json_encode(['code' => 201, 'msg' => 'action_type类型错误', 'data' => [], 'connections' => self::$connection_count]));
}
}
} else {
$connection->send(json_encode(['code' => 201, 'msg' => '数据请求为空', 'data' => [], 'connections' => self::$connection_count]));
}
} //关闭链接 处理逻辑
public static function onClose($connection) {
//检索$connection->id 是否有在self::$room_connection_array中,有的话就剔除 foreach (self::$room_connection_array as $k => $v) {
foreach ($v as $kk => $vv) {
if ($kk == $connection->id) {
unset(self::$room_connection_array[$k][$connection->id]);
}
}
}
// p(self::$room_connection_array['100']);
} }
{"action_type":"login","is_login":1,"room_id":101}  //登录

{"action_type":"broadcast_to_all","room_id":100,"message":"111"} //发送消息

为什么不用switch代码会看起来更清晰,因为有bug,对字符串匹配的不好
注意:
1,$connection就是当前的连接数据
2,因为未根据work id做房间划分,不知道在超出单个work连接时候会不会出问题
3,可以根据实际压力去划分一个work的最大连接数,这里是简单的测试demo所以未做具体的细节划分
4,这里应该结合session来做处理数据,但是我只是根据发送数据来区别用户,你可以在登录的发送数据的时候根据session处理数据,看需要,必须要返回用户列表,就直接把room id下面的所有用户名返回就OK
5,workerman用起来其实还是比较简单的,但是我这种结合laravel的整合是有问题,比如现在我有一个消息推送,一个聊天室就没办法放在一起使用,必须用别的办法,如果是单功能就比较容易,直接结合,我有一个骚办法就是直接
复制artisan入口文件,直接增加新入口artisan1,经过测试完全没有问题,但是其实不是很好的解决方案,如果要用就先这么上吧 如果你觉得麻烦可以是gateway做比较简单
 

2019年7月12日09:43:56

注意:上面是临时测试代码。业务代码使用try catch处理异常和错误

laravel整合workerman做聊天室的更多相关文章

  1. laravel整合workerman做消息推送系统

    官方建议分离 workerman和mvc框架的结合,我去,这不是有点脑缺氧吗? 大量的业务逻辑,去独立增加方法和类库在写一次,实际业务中是不现实和不实际的 gateway增加一些这方面的工作,但是我看 ...

  2. Spring Boot2 系列教程 (十七) | 整合 WebSocket 实现聊天室

    微信公众号:一个优秀的废人.如有问题,请后台留言,反正我也不会听. 前言 昨天那篇介绍了 WebSocket 实现广播,也即服务器端有消息时,将消息发送给所有连接了当前 endpoint 的浏览器.但 ...

  3. Workerman创建聊天室实例

    // 标记是全局启动 define('GLOBAL_START', 1); require_once __DIR__ . '/Workerman/Connection.php'; require_on ...

  4. workerman搭建聊天室

    首先,先打开官网手册   http://doc.workerman.net/ 根据手册里安装里的提示,完成环境检测,和安装对应的扩展,并把对应的WorkerMan代码包下载解压至根目录 在根目录下创建 ...

  5. 使用nodejs引用socket.io做聊天室

    Server: var app = require('http').createServer(handler) , io = require('socket.io').listen(app) , fs ...

  6. 百行go代码构建p2p聊天室

    百行go代码构建p2p聊天室 百行go代码构建p2p聊天室 1. 上手使用 2. whisper 原理 3. 源码解读 3.1 参数说明 3.1 连接主节点 3.2 我的标识 3.2 配置我的节点 3 ...

  7. 以太坊系列之十八: 百行go代码构建p2p聊天室

    百行go代码构建p2p聊天室 百行go代码构建p2p聊天室 1. 上手使用 2. whisper 原理 3. 源码解读 3.1 参数说明 3.1 连接主节点 3.2 我的标识 3.2 配置我的节点 3 ...

  8. 对接融云即时通讯组件SDK,轻松实现App聊天室

    我好像特别喜欢做聊天室类的东东,刚折腾完微软的SignalR又折腾App.本来想研究研究XMPP的,由于服务器的搭建问题,先采用一个第三方的吧,看看效果如何.听到弟弟说他们公司用到了融云,我也下载个S ...

  9. 使用原生node写一个聊天室

    在学习node的时候都会练习做一个聊天室的项目,主要使用socket.io模块和http模块.这里我们使用更加原始的方式去写一个在命令行聊天的聊天室. http模块,socket.io都是高度封装之后 ...

随机推荐

  1. 【转】史上最详细的Composer安装tp5教程

    http://www.thinkphp.cn/topic/52362.html Composer安装tp5教程1.下载composer先介绍几个网站Composer官网https://getcompo ...

  2. 第29月第14天 evpp

    1.evpp https://github.com/Qihoo360/evpp/tree/master/examples/recipes/self_control_timer https://blog ...

  3. XML与HTML的作用不同

    1. html是用来显示数据的:xml是用来描述数据.存放数据的,所以可以作为持久化的介质!Html将数据和显示结合在一起,在页面中把这数据显示出来:xml 则将数据和显示分开. XML被设计用来描述 ...

  4. oracle用命令创建表空间、用户,并为用户授权、收回权限。

    oracle中如何删除用户? Oracle中使用DROP USER来删除用户,如果使用DROP USER CASCADE那么用户的对象也同时被删除掉.为了达到删除用户的效果而又不影响对用户下的对象的使 ...

  5. Windows密钥容器和证书的关系

    其实CSP主要是对容器里的密钥对操作的,和证书关系不大. 容器里的密钥对有两种类型:一种是AT_KEYEXCHANGE,表示加密的密钥对,一种是AT_SIGNATURE表示签名的密钥对. 由于美国的出 ...

  6. OpenCV3编程入门读书笔记5-边缘检测

    一.边缘检测的一般步骤 1.滤波 边缘检测的算法主要是基于图像强度的一阶和二阶导数,但导数通常对噪声很敏感,因此必须采用滤波器来改善与噪声有关的边缘检测器的性能. 2.增强 增强边缘的基础是确定图像各 ...

  7. 帆软报表(finereport)参数组合/下拉参数联动

    首先实现下拉参数联动 1.参数的定义→添加控件绑定数据→参数过滤和参数面板样式 下拉复选框控件注意事项:select * from tablewhere 1=1${if(len(控件名称)=0,&qu ...

  8. .Net Core ----通过XUnit进行接口单元测试(带请求头及参数)并用output输出结果

    最近在做core的接口单元测试,所以在这拿出来分享一下,添加XUnit的nuget包 话不多说,直接上代码了: 输出结果(需要的命名空间using Xunit.Abstractions;): ITes ...

  9. Team Queue (HDU:1387)

    Queues and Priority Queues are data structures which are known to most computer scientists. The Team ...

  10. add web server(nginx+apache)

    #!/bin/bash # # Web Server Install Script # Last Updated 2012.09.24 # ##### modify by WanJie 2012.09 ...