第一步:安装thinkpph程序包

第二步:切换到根目录,使用composer require workerman/gateway-worker 安装Linux版本的gateway。(前提是你服务器安装了composer )

http://www.workerman.net/workerman-chat 下载官方实例:workerman-chat  将文件夹内的applications\chat\Web\下的文件上传到:\public\static\index下

第三部:在public目录下:新建server.php

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +---------------------------------------------------------------------- // [ 应用入口文件 ] // 定义应用目录
define('APP_PATH', __DIR__ . '/../application/');
define('BIND_MODULE','gateway/Run');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';

切换到:public目录下执行:php server.php start

第四部:新建gateway模块 下建三个控制器:

(1)Run.php

<?php
namespace app\gateway\controller;
use think\Controller;
use Workerman\Worker;
use GatewayWorker\Register;
use GatewayWorker\BusinessWorker;
use GatewayWorker\Gateway; class Run
{
public function __construct()
{
// 初始化register
new Register('text://0.0.0.0:1236'); //初始化 bussinessWorker 进程
$worker = new BusinessWorker();
$worker->name = 'RoomBusinessWorker';
$worker->count = 4;
$worker->registerAddress = '127.0.0.1:1236'; // 设置处理业务的类,此处制定Events的命名空间
$worker->eventHandler = '\app\gateway\controller\Events';
// 初始化 gateway 进程
$gateway = new Gateway("websocket://0.0.0.0:7272");
$gateway->name = 'RoomGateway';
$gateway->count = 4;
$gateway->lanIp = '127.0.0.1';
$gateway->startPort = 2900;
$gateway->registerAddress = '127.0.0.1:1236'; // 运行所有Worker;
Worker::runAll();
}
}

(2) Events.php

<?php

namespace app\gateway\controller;

use GatewayWorker\Lib\Gateway;
use think\Controller; class Events extends Controller
{
/**
* 有消息时
* @param integer $client_id 连接的客户端
* @param mixed $message
* @return void
*/
public static function onMessage($client_id, $message)
{
// debug
echo "client:{$_SERVER['REMOTE_ADDR']}:{$_SERVER['REMOTE_PORT']} gateway:{$_SERVER['GATEWAY_ADDR']}:{$_SERVER['GATEWAY_PORT']} client_id:$client_id session:".json_encode($_SESSION)." onMessage:".$message."\n"; // 客户端传递的是json数据
$message_data = json_decode($message, true);
if(!$message_data)
{
return ;
} // 根据类型执行不同的业务
switch($message_data['type'])
{
// 客户端回应服务端的心跳
case 'pong':
return;
// 客户端登录 message格式: {type:login, name:xx, room_id:1} ,添加到客户端,广播给所有客户端xx进入聊天室
case 'login':
// 判断是否有房间号
if(!isset($message_data['room_id']))
{
throw new \Exception("\$message_data['room_id'] not set. client_ip:{$_SERVER['REMOTE_ADDR']} \$message:$message");
} // 把房间号昵称放到session中
$room_id = $message_data['room_id'];
$client_name = htmlspecialchars($message_data['client_name']);
$_SESSION['room_id'] = $room_id;
$_SESSION['client_name'] = $client_name; // 获取房间内所有用户列表
$clients_list = Gateway::getClientSessionsByGroup($room_id);
foreach($clients_list as $tmp_client_id=>$item)
{
$clients_list[$tmp_client_id] = $item['client_name'];
}
$clients_list[$client_id] = $client_name; // 转播给当前房间的所有客户端,xx进入聊天室 message {type:login, client_id:xx, name:xx}
$new_message = array('type'=>$message_data['type'], 'client_id'=>$client_id, 'client_name'=>htmlspecialchars($client_name), 'time'=>date('Y-m-d H:i:s'));
Gateway::sendToGroup($room_id, json_encode($new_message));
Gateway::joinGroup($client_id, $room_id); // 给当前用户发送用户列表
$new_message['client_list'] = $clients_list;
Gateway::sendToCurrentClient(json_encode($new_message));
return; // 客户端发言 message: {type:say, to_client_id:xx, content:xx}
case 'say':
// 非法请求
if(!isset($_SESSION['room_id']))
{
throw new \Exception("\$_SESSION['room_id'] not set. client_ip:{$_SERVER['REMOTE_ADDR']}");
}
$room_id = $_SESSION['room_id'];
$client_name = $_SESSION['client_name']; // 私聊
if($message_data['to_client_id'] != 'all')
{
$new_message = array(
'type'=>'say',
'from_client_id'=>$client_id,
'from_client_name' =>$client_name,
'to_client_id'=>$message_data['to_client_id'],
'content'=>"<b>对你说: </b>".nl2br(htmlspecialchars($message_data['content'])),
'time'=>date('Y-m-d H:i:s'),
);
Gateway::sendToClient($message_data['to_client_id'], json_encode($new_message));
$new_message['content'] = "<b>你对".htmlspecialchars($message_data['to_client_name'])."说: </b>".nl2br(htmlspecialchars($message_data['content']));
return Gateway::sendToCurrentClient(json_encode($new_message));
} $new_message = array(
'type'=>'say',
'from_client_id'=>$client_id,
'from_client_name' =>$client_name,
'to_client_id'=>'all',
'content'=>nl2br(htmlspecialchars($message_data['content'])),
'time'=>date('Y-m-d H:i:s'),
);
return Gateway::sendToGroup($room_id ,json_encode($new_message));
}
} /**
* 当客户端断开连接时
* @param integer $client_id 客户端id
*/
public static function onClose($client_id)
{
// debug
echo "client:{$_SERVER['REMOTE_ADDR']}:{$_SERVER['REMOTE_PORT']} gateway:{$_SERVER['GATEWAY_ADDR']}:{$_SERVER['GATEWAY_PORT']} client_id:$client_id onClose:''\n"; // 从房间的客户端列表中删除
if(isset($_SESSION['room_id']))
{
$room_id = $_SESSION['room_id'];
$new_message = array('type'=>'logout', 'from_client_id'=>$client_id, 'from_client_name'=>$_SESSION['client_name'], 'time'=>date('Y-m-d H:i:s'));
Gateway::sendToGroup($room_id, json_encode($new_message));
}
} /**
* 当用户连接时触发的方法
* @param integer $client_id 连接的客户端
* @return void
*/
public static function onConnect($client_id)
{
Gateway::sendToClient($client_id, "Your client_id is $client_id");
} /**
* 当用户断开连接时触发的方法
* @param integer $client_id 断开连接的客户端
* @return void
*/
// public static function onClose($client_id)
// {
// Gateway::sendToAll("client[$client_id] logout\n");
// } /**
* 当进程启动时
* @param integer $businessWorker 进程实例
*/
public static function onWorkerStart($businessWorker)
{
echo "WorkerStart\n";
} /**
* 当进程关闭时
* @param integer $businessWorker 进程实例
*/
public static function onWorkerStop($businessWorker)
{
echo "WorkerStop\n";
}
}

(3)index.php

<?php
namespace app\gateway\controller;
use think\Controller; class Index extends Controller
{
public function index()
{
return $this->fetch();
}
}

第五部:gateway模块下新建视图文件:

<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>workerman-chat PHP聊天室 Websocket(HTLM5/Flash)+PHP多进程socket实时推送技术</title>
<link href="/static/index/css/bootstrap.min.css" rel="stylesheet">
<link href="/static/index/css/style.css" rel="stylesheet"> <script type="text/javascript" src="/static/index/js/swfobject.js"></script>
<script type="text/javascript" src="/static/index/js/web_socket.js"></script>
<script type="text/javascript" src="/static/index/js/jquery.min.js"></script> <script type="text/javascript">
if (typeof console == "undefined") { this.console = { log: function (msg) { } };}
// 如果浏览器不支持websocket,会使用这个flash自动模拟websocket协议,此过程对开发者透明
WEB_SOCKET_SWF_LOCATION = "/static/index/swf/WebSocketMain.swf";
// 开启flash的websocket debug
WEB_SOCKET_DEBUG = true;
var ws, name, client_list={}; // 连接服务端
function connect() {
// 创建websocket
ws = new WebSocket("ws://"+document.domain+":7272");
// 当socket连接打开时,输入用户名
ws.onopen = onopen;
// 当有消息时根据消息类型显示不同信息
ws.onmessage = onmessage;
ws.onclose = function() {
console.log("连接关闭,定时重连");
connect();
};
ws.onerror = function() {
console.log("出现错误");
};
} // 连接建立时发送登录信息
function onopen()
{
if(!name)
{
show_prompt();
}
// 登录
var login_data = '{"type":"login","client_name":"'+name.replace(/"/g, '\\"')+'","room_id":"<?php echo isset($_GET['room_id']) ? $_GET['room_id'] : 1?>"}';
console.log("websocket握手成功,发送登录数据:"+login_data);
ws.send(login_data);
} // 服务端发来消息时
function onmessage(e)
{
console.log(e.data);
var data = eval("("+e.data+")");
switch(data['type']){
// 服务端ping客户端
case 'ping':
ws.send('{"type":"pong"}');
break;;
// 登录 更新用户列表
case 'login':
//{"type":"login","client_id":xxx,"client_name":"xxx","client_list":"[...]","time":"xxx"}
say(data['client_id'], data['client_name'], data['client_name']+' 加入了聊天室', data['time']);
if(data['client_list'])
{
client_list = data['client_list'];
}
else
{
client_list[data['client_id']] = data['client_name'];
}
flush_client_list();
console.log(data['client_name']+"登录成功");
break;
// 发言
case 'say':
//{"type":"say","from_client_id":xxx,"to_client_id":"all/client_id","content":"xxx","time":"xxx"}
say(data['from_client_id'], data['from_client_name'], data['content'], data['time']);
break;
// 用户退出 更新用户列表
case 'logout':
//{"type":"logout","client_id":xxx,"time":"xxx"}
say(data['from_client_id'], data['from_client_name'], data['from_client_name']+' 退出了', data['time']);
delete client_list[data['from_client_id']];
flush_client_list();
}
} // 输入姓名
function show_prompt(){
name = prompt('输入你的名字:', '');
if(!name || name=='null'){
name = '游客';
}
} // 提交对话
function onSubmit() {
var input = document.getElementById("textarea");
var to_client_id = $("#client_list option:selected").attr("value");
var to_client_name = $("#client_list option:selected").text();
ws.send('{"type":"say","to_client_id":"'+to_client_id+'","to_client_name":"'+to_client_name+'","content":"'+input.value.replace(/"/g, '\\"').replace(/\n/g,'\\n').replace(/\r/g, '\\r')+'"}');
input.value = "";
input.focus();
} // 刷新用户列表框
function flush_client_list(){
var userlist_window = $("#userlist");
var client_list_slelect = $("#client_list");
userlist_window.empty();
client_list_slelect.empty();
userlist_window.append('<h4>在线用户</h4><ul>');
client_list_slelect.append('<option value="all" id="cli_all">所有人</option>');
for(var p in client_list){
userlist_window.append('<li id="'+p+'">'+client_list[p]+'</li>');
client_list_slelect.append('<option value="'+p+'">'+client_list[p]+'</option>');
}
$("#client_list").val(select_client_id);
userlist_window.append('</ul>');
} // 发言
function say(from_client_id, from_client_name, content, time){
$("#dialog").append('<div class="speech_item"><img src="http://lorempixel.com/38/38/?'+from_client_id+'" class="user_icon" /> '+from_client_name+' <br> '+time+'<div style="clear:both;"></div><p class="triangle-isosceles top">'+content+'</p> </div>');
} $(function(){
select_client_id = 'all';
$("#client_list").change(function(){
select_client_id = $("#client_list option:selected").attr("value");
});
});
</script>
</head>
<body onload="connect();">
<div class="container">
<div class="row clearfix">
<div class="col-md-1 column">
</div>
<div class="col-md-6 column">
<div class="thumbnail">
<div class="caption" id="dialog"></div>
</div>
<form onsubmit="onSubmit(); return false;">
<select style="margin-bottom:8px" id="client_list">
<option value="all">所有人</option>
</select>
<textarea class="textarea thumbnail" id="textarea"></textarea>
<div class="say-btn"><input type="submit" class="btn btn-default" value="发表" /></div>
</form>
<div>
&nbsp;&nbsp;&nbsp;&nbsp;<b>房间列表:</b>(当前在&nbsp;房间<?php echo isset($_GET['room_id'])&&intval($_GET['room_id'])>0 ? intval($_GET['room_id']):1; ?>)<br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="/?room_id=1">房间1</a>&nbsp;&nbsp;&nbsp;&nbsp;<a href="/?room_id=2">房间2</a>&nbsp;&nbsp;&nbsp;&nbsp;<a href="/?room_id=3">房间3</a>&nbsp;&nbsp;&nbsp;&nbsp;<a href="/?room_id=4">房间4</a>
<br><br>
</div>
<p class="cp">PHP多进程+Websocket(HTML5/Flash)+PHP Socket实时推送技术&nbsp;&nbsp;&nbsp;&nbsp;Powered by <a href="http://www.workerman.net/workerman-chat" target="_blank">workerman-chat</a></p>
</div>
<div class="col-md-3 column">
<div class="thumbnail">
<div class="caption" id="userlist"></div>
</div>
<a href="#" target="_blank"><img style="width:252px;margin-left:5px;" src="/static/index/img/workerman-todpole.png"></a>
</div>
</div>
</div>
</body>
</html>

见目录:

最终效果:

记得在linux系统中把使用的端口允许访问

tp5和gateworer集成的更多相关文章

  1. tp5集成淘宝,微信,网易,新浪等第三方登录

    tp5集成淘宝,微信,网易,新浪等第三方登录 一.总结 一句话总结: 接口 链接 实现的话就是这些平台给的一个接口(链接),你通过这些接口登录进去之后,它会给你返回用户名,头像之类的信息,我们的网站存 ...

  2. tp5 集成 layui富文本编辑器

    编辑器地址:http://www.layui.com/doc/modules/layedit.html 一睹芳容 1 去官网:http://www.layui.com/     下载layui ├─c ...

  3. tp5对接支付宝支付简单集成

    对于每个刚开始工作的新手来说,无论支付宝支付还是微信支付都是跑不掉的一个小门槛. 在加上本人比较技术比较渣(比较懒导致的),不太喜欢引用那么大的SDK,于是就简单集成了一下支付宝的支付. 但也只是只有 ...

  4. TODO:macOS上ThinkPHP5和Semantic-UI集成

    TODO:macOS上ThinkPHP5和Semantic-UI集成 1. 全局安装 (on OSX via homebrew)Composer 是 homebrew-php 项目的一部分 2. 把X ...

  5. 在wamp集成环境下安装laravel5.2.*框架

    虽然官方一直强烈推荐使用homestead,但是这个相对麻烦一点,所以我还是选择使用wamp集成开发环境.还有这里我只讲解windows系统下的安装,其他例如mac或linux就不写了,此文章是面向刚 ...

  6. tp5 整合 个推

    这里因为业务需要使用推送功能 uni 里面前端集成了个推 所以选择了个推来做推送. 个推的官方文档地址: http://docs.getui.com/getui/server/php/start/ 在 ...

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

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

  8. ThinkPHP5集成JS-SDK实现微信自定义分享功能

    最近开发一个项目,需要将链接分享给好友时能够自定义标题.简介和logo,现将ThinkPHP5集成JS-SDK实现微信自定义分享功能的过程整理成文. 一.准备工作 1.认证的公众号 不管是订阅号还是服 ...

  9. TP5视频教程课程内容

    <TP5 视频教程课程内容> 一.ThinkPHP5TP5 官网基础教程, 官网手册作为参考,讲解TP5的使用方法.理解TP的用途 二.TP5大型项目实战及底层源码分析用TP5 做大型电商 ...

随机推荐

  1. 如何查看 ThinkPHP5.1 的升级说明

    如何查看 ThinkPHP5.1 的升级说明 ThinkPHP 官方对于升级历史都有说明,这个官方做的非常不错. 在官方的手册中就有. 比如从 ThinkPHP 5.1.26 升级到 ThinkPHP ...

  2. Android 基础题目

    1. BroadcastReceiver 在UI thread? BroadcastReceiver 总是在UI thread, If you register your BroadcastRecei ...

  3. CentOS7.2部署FTP

    目前Linux大部分部署的FTP服务器都是vsftpd,至于为什么,暂时没什么必要深究. 1.安装vsftpd # yum check-update //检查可更新的程序,也可以不更新直接安装,以防万 ...

  4. emacs之配置php

    php-setting.el (require 'php-mode) 以后丰富

  5. bzoj 3879: SvT

    Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始 ...

  6. 在eclipse中使用mybatis-generator自动创建代码

    1.eclipse中安装插件,地址:http://mybatis.googlecode.com/svn/sub-projects/generator/trunk/eclipse/UpdateSite/ ...

  7. Hadoop详细安装配置过程

    步骤一:基础环境搭建 1.下载并安装ubuntukylin-15.10-desktop-amd64.iso 2.安装ssh sudo apt-get install openssh-server op ...

  8. Python web框架——Tornado

    Tornado是一个Python Web框架和异步网络库,最初由FriendFeed开发.通过使用非阻塞网络I / O,Tornado可以扩展到数万个开放连接,使其成为需要长时间连接每个用户的长轮询, ...

  9. 765. Couples Holding Hands

    ▶ n 对夫妻共 2n 个人随机坐成一排,“交换其中某两人的位置” 称为一次操作,求最少的操作此次数,使 n 对夫妻两人都相邻.初始座位为非负整数列 D1n-1,其中值为 2k 和 2k+1 的两个元 ...

  10. 使用http-proxy-middleware 代理跨域

    使用http-proxy-middleware 代理跨域 例如请求的url:“http://f.apiplus.cn/bj11x5.json” 1.打开config/index.js,在proxyTa ...