GatewayWorker 结合 Laravel 使用的简单案例,重点是在Laravel中使用GatewayClient发送消息

主要流程:GatewayWorker主要负责推送消息给客户端但不接受客户端数据,Laravel主要负责接受客户端数据并处理业务逻辑,然后使用GatewayClient推送数据,

示意图拿一个官方图片哈 http://www.workerman.net/gatewaydoc/work-with-other-frameworks/README.html

跟Laravel结合使用的优点:

1,当 GatewayWorker服务运行时,修改了Laravel业务代码,直接推送业务相关代码到服务器上即可,不用重启GatewayWorker服务;

2,可以尽情使用Laravel提供的各种便利工具处理数据和业务逻辑;

整个项目压缩文件太大不便上传,接下来直接贴代码咯,

本地windows使用步骤:

1,启动GatewayWorker,双击 start_for_win.bat

2,新建一个虚拟域名路径指定到该项目public目录

3,开两个浏览器页面就能互发消息了,如下面两个效果图,

效果图:

项目结构:

ChatServer目录下的4个start_*.php文件是直接复制的官方demo https://github.com/walkor/workerman-chat/tree/master/Applications/Chat

 composer.json 的 require 部分

    "require": {
"php": ">=7.0.0",
"fideloper/proxy": "~3.3",
"laravel/framework": "5.5.*",
"laravel/tinker": "~1.0",
"workerman/gateway-worker" : ">=3.0.0",
"workerman/gatewayclient": "^3.0"
},

start_for_win.bat  本地windows启动脚本 

php app\ChatServer\start_register.php app\ChatServer\start_web.php app\ChatServer\start_gateway.php app\ChatServer\start_businessworker.php
pause

 start.php  服务器上的启动脚本

<?php
/**
* run with command
* php start.php start
*/ ini_set('display_errors', 'on');
use Workerman\Worker; if(strpos(strtolower(PHP_OS), 'win') === 0)
{
exit("start.php not support windows, please use start_for_win.bat\n");
} // 检查扩展
if(!extension_loaded('pcntl'))
{
exit("Please install pcntl extension. See http://doc3.workerman.net/appendices/install-extension.html\n");
} if(!extension_loaded('posix'))
{
exit("Please install posix extension. See http://doc3.workerman.net/appendices/install-extension.html\n");
} // 标记是全局启动
define('GLOBAL_START', 1); require_once __DIR__ . '/vendor/autoload.php'; // 加载所有application/*/start.php,以便启动所有服务
foreach(glob(__DIR__.'/app/ChatServer/start*.php') as $start_file)
{
require_once $start_file;
}
// 运行所有服务
Worker::runAll();

Events.php  参考 http://www.workerman.net/gatewaydoc/work-with-other-frameworks/README.html

<?php

/**
* 用于检测业务代码死循环或者长时间阻塞等问题
* 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload
* 然后观察一段时间workerman.log看是否有process_timeout异常
*/
//declare(ticks=1); use \GatewayWorker\Lib\Gateway;
class Events
{
// 当有客户端连接时,将client_id返回,让mvc框架判断当前uid并执行绑定
public static function onConnect($client_id)
{
Gateway::sendToClient($client_id, json_encode(array(
'type' => 'init',
'client_id' => $client_id
)));
} // GatewayWorker建议不做任何业务逻辑,onMessage留空即可
public static function onMessage($client_id, $message)
{ }
}
IndexController.php  发送消息用的控制器 参考 http://www.workerman.net/gatewaydoc/work-with-other-frameworks/README.html
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use GatewayClient\Gateway; class IndexController extends Controller
{
public function __construct()
{
Gateway::$registerAddress = '127.0.0.1:1236';
} /**
* web客户端
* @param string $uid
* @param string $to_uid
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function client()
{
return view('client');
} /**
* 绑定uid
* @return mixed
*/
public function bind()
{
// 假设用户已经登录,用户uid和群组id在session中
$uid = request('uid');
$client_id = request('client_id'); $res = request()->all();
$res['type'] = 'bind';
$res['time'] = date('H:i:s');
// client_id与uid绑定
Gateway::bindUid($client_id, $uid);
Gateway::sendToUid($uid, json_encode($res));
return response()->json($res);
} /**
* 发送消息
* @return mixed
*/
public function send()
{
$uid = request('uid');
$to_uid = request('to_uid');
$res = request()->all();
$res['type'] = 'send';
$res['time'] = date('H:i:s');
// 向任意uid的网站页面发送数据
Gateway::sendToUid($uid, json_encode($res));
Gateway::sendToUid($to_uid, json_encode($res));
return response()->json($res);
}
}

web.php  路由 

<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/ Route::get('/', function () {
return view('welcome');
}); Route::match(['post', 'get'], 'index/index/{uid}/{to_uid}', 'IndexController@client'); Route::match(['post', 'get'], 'index/client/{uid}/{to_uid}', 'IndexController@client'); Route::match(['post', 'get'], 'index/bind', 'IndexController@bind'); Route::match(['post', 'get'], 'index/send', 'IndexController@send');

client.blade.php   web客户端视图 

<html>
<head>
<title>{{ request('uid') }} => {{ request('to_uid') }}</title>
<link href="https://cdn.bootcss.com/normalize/8.0.0/normalize.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.js"></script>
<script src="https://cdn.bootcss.com/json5/0.5.1/json5.js"></script>
<style>
* {
padding: 0;
margin: 0;
} .chat-main {
width: 600px;
margin: 30px auto;
box-shadow: 0 0 1px gray;
border: 1px solid gray;
line-height: 1.5em;
} .chat-header {
border-bottom: 1px solid gray;
padding: 5px 15px;
} .chat-log {
height: 200px;
overflow-y: auto;
border-bottom: 1px solid gray;
padding: 5px 15px;
} .chat-log dl {
margin: 15px 0;
} .chat-log dl dd {
display: inline-block;
border: 1px solid gray;
padding: 5px 15px;
border-radius: 10px;
border-top-left-radius: 0;
} .chat-log dl.me dd {
border-radius: 10px;
border-top-right-radius: 0;
} .chat-log dl.me {
text-align: right;
} .chat-log dl.me dd {
text-align: left;
} .user-link {
float: right;
} .user-link a {
margin-left: 5px;
} .hide {
display: none;
} .inline-block {
display: inline-block;
} .btn {
text-align: right;
padding: 5px 15px 15px;
} #btn-send {
display: inline-block;
background: white;
border: 1px solid gray;
line-height: 2em;
padding: 0 2em;
outline: none;
} #btn-send:focus {
background: white;
border-color: green;
} #message {
display: block;
width: 570px;
height: 100px;
margin: 15px auto 0;
border: 1px solid gray;
overflow-x: hidden;
overflow-y: auto;
resize: none;
outline: none;
padding: 10px;
} #message:focus {
border-color: green;
} .chat-body > .tpl {
display: none;
}
</style>
</head>
<body> <div class="hide">
bind<input type="text" id="bind" value="{{ url('index/bind') }}"><br>
send<input type="text" id="send" value="{{ url('index/send') }}"><br>
</div> <div class="chat-main">
<div class="chat-header">
<div class="chat-title inline-block">
{{ request('uid') }} => {{ request('to_uid') }}
</div>
<div class="user-link inline-block">
<span class="inline-block">模拟用户</span>
<a class="inline-block" href="{{ url('index/index',['uid'=>1111,'to_uid'=>2222]) }}">1111</a>
<a class="inline-block" href="{{ url('index/index',['uid'=>2222,'to_uid'=>1111]) }}" target="_blank">2222</a>
</div>
</div>
<div class="chat-body">
<div class="chat-log"> </div>
<dl class="tpl">
<dt>1111(12:00:00)</dt>
<dd>aaaabbbbbb</dd>
</dl>
</div>
<div class="chat-footer">
<form action="" id="form">
<div class="hide">
cliend_id<input type="text" name="client_id" id="client_id" value="{{ request('uid') }}"><br>
uid<input type="text" name="uid" id="uid" value="{{ request('uid') }}"><br>
to_uid<input type="text" name="to_uid" value="{{ request('to_uid') }}"><br>
</div>
<textarea name="message" id="message" cols="30" rows="10"></textarea>
<div class="btn">
<button type="button" id="btn-send">发 送</button>
</div>
</form>
</div>
</div> <script> /**
* 与GatewayWorker建立websocket连接,域名和端口改为你实际的域名端口,
* 其中端口为Gateway端口,即start_gateway.php指定的端口。
* start_gateway.php 中需要指定websocket协议,像这样
* $gateway = new Gateway(websocket://0.0.0.0:7272);
*/
ws = new WebSocket("ws://127.0.0.1:7272");
// 服务端主动推送消息时会触发这里的onmessage
ws.onmessage = function (e) {
// json数据转换成js对象
var data = JSON5.parse(e.data);
var type = data.type || '';
switch (type) {
// Events.php中返回的init类型的消息,将client_id发给后台进行uid绑定
case 'init':
$('#client_id').val(data.client_id);
// 利用jquery发起ajax请求,将client_id发给后端进行uid绑定
$.get($('#bind').val(), $('#form').serialize(), function (res) {
console.log('bind', res);
}, 'json');
break;
case 'send':
var $tpl = $('.chat-body>.tpl').clone().show(); if (data.uid == $('#uid').val()) {
$tpl.find('dt').html('(' + data.time + ') ' + data.uid);
$tpl.addClass('me')
} else {
$tpl.find('dt').html(data.uid + ' (' + data.time + ')');
} $tpl.find('dd').html(data.message.replace(/\n/gim, '<br>')); $('.chat-log').append($tpl); scrollBottom();
break;
// 当mvc框架调用GatewayClient发消息时直接alert出来
default:
console.log('default', e.data);
}
}; $('#form').submit(function (e) {
return false;
}); var isScrollBottom = true; function scrollBottom(){
if (isScrollBottom) {
$('.chat-log').scrollTop($('.chat-log')[0].scrollHeight);
}
} $('#btn-send').click(function (e) {
if ($.trim($('#message').val())) {
$.get($('#send').val(), $('#form').serialize(), function (res) {
console.log('send', res);
$('#message').val('');
scrollBottom();
}, 'json');
}
}); $('.chat-log').scroll(function (e) {
var outerHeight = $(this).outerHeight();
var scrollTop = $(this).scrollTop();
var scrollHeight = $(this)[0].scrollHeight;
if (outerHeight + scrollTop >= scrollHeight - 15) {
isScrollBottom = true;
} else {
isScrollBottom = false;
}
})
</script> </body>
</html>

==============================================

本文链接 https://www.cnblogs.com/stumpx/p/9156850.html

==============================================

GatewayWorker+Laravel demo的更多相关文章

  1. 使用GatewayWorker 开发个即时聊天demo

    前言: 上手册以示尊重:https://www.kancloud.cn/walkor/gateway-worker/326138: https://www.cnblogs.com/fuqiang88/ ...

  2. 聊天室(下篇)GatewayWorker 与 Laravel 的整合

    思路 上一篇大概梳理了一下 GatewayWorker 的基础知识.这篇就来准备整合 GatewayWorker 到 Laravel. GatewayWorker 是基于 Socket 监听的服务器框 ...

  3. 02 workerman之GatewayWorker简单的demo 实现两端发送消息

    前端代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <t ...

  4. laravel的中间件demo

    过滤器已经被废除...刚学才两天,蛋疼 创建一个中间件 ./artisan make:middleware TestMiddleware 大概代码 <?php namespace App\Htt ...

  5. Laravel 5.3 请求处理管道详解

    对于一个Web应用来说,在一个请求真正处理前,我们可能会对请求做各种各样的判断,然后才允许后续处理. 我们通常的做法: Script 01.php Script 02.php 优点:直观,容易理解 缺 ...

  6. 在window下配置laravel开发环境

    1.由于有一点php基础,所以非常想更进一步,就选择据说在国外最流行的php框架来学习了,laravel框架,官网上介绍是为艺术而生,从知乎和一些论坛上看到,laravel学起来并不简单,首先配置问题 ...

  7. laravel 指定 版本安装

    composer create-project laravel/laravel=5.0.* --prefer-dist composer create-project laravel/laravel= ...

  8. php后台开发(二)Laravel框架

    php后台开发(二)Laravel框架 为了提高后台的开发效率,往往需要选择一套适合自己的开发框架,因此,选择了功能比较完善的Laravel框架,仔细学来,感觉和Python语言的框架Django非常 ...

  9. Laravel 5 基础(十二)- 认证

    Laravel 出厂已经带有了用户认证系统,我们来看一下 routes.php,如果删除了,添加上: Route::controllers([ 'auth' => 'Auth\AuthContr ...

随机推荐

  1. WHU-1551-Pairs(莫队算法+分块实现)

    Description Give you a sequence consisted of n numbers. You are required to answer how many pairs of ...

  2. 【教程】怎样申请Chrome应用商店(Web Store)开发人员

    首先你须要一张信用卡,假设你没有的话.能够借用父母或他人的(多见于学生党) 假设你有信用卡.你还得看看信用卡正面是否有注明"VISA"."MasterCard" ...

  3. Real-Time Compressive Tracking 论文笔记

    总体思想 1 利用符合压缩感知RIP条件的随机感知矩阵对多尺度图像进行降维 2 然后对降维的特征採用简单的朴素贝叶斯进行分类 算法主要流程 1 在t帧的时候,我们採样得到若干张目标(正样本)和背景(负 ...

  4. 命题作文:在一棵IPv4地址树中彻底理解IP路由表的各种查找过程

    这是一篇命题作文.近期一直想写点东西,但一直找不到题目.正好收到一封邮件,有人问我Linux路由表的布局问题以及路由缓存的问题,加之前些日子又帮人做了一个片上路由表,所以认为这是个好题目,索性花了多半 ...

  5. win10访问共享文件夹提示:引用的账户当前已锁定,且当前可能无法登陆

    最近一台电脑访问windows 2008 R2 server的共享文件夹.没有使用域环境. win10界面提示:引用的账户当前已锁定,且当前可能无法登陆. 登陆2008发现,该账户的确锁定.猜测可能该 ...

  6. 2016/05/11 Thinkphp 3.2.2 验证码 使用 及校验

    先新建一个公共控制器,用于放置验证码的实例化代码(不用新建控制器也行,任意公共控制器都可以). 例如:PublicController.class.php 4 5 6 7 8 9 10 11 12 1 ...

  7. C项目案例实践(0)-语言基础

    1.C语言数据类型 所谓数据类型是按被定义变量的性质.表示形式.占据存储空间的多少.构造特点来划分的.C中数据类型可分为基本数据类型.构造数据类型.指针类型.空类型4大类,结构如图: (1)基本数据类 ...

  8. 修改phpmyadmin中的默认超时时间

    phpmyadmin在使用过程中经常出现"登陆超时(1440秒未活动),请重新登录",很烦 解决方法如下: 第一步: 修改php.ini,找到 session.gc_maxlife ...

  9. linux永久或临时修改dns

    1.临时修改网卡DNS地址 sudo vim /etc/resolv.conf 改为如下内容: nameserver 8.8.8.8 #修改成你的主DNS nameserver 8.8.4.4 #修改 ...

  10. java 类属性、方法加载的顺序

    1.静态变量 2.静态代码块 3.局部代码块 4.构造函数 5.普通代码块 6.静态方法 7.普通方法 8.普通属性