thinkphp5整合 gatewaywork實現聊天

1:將下載的gatewaywork下的\vendor  下的workman文件夾,整個複製到tp5下的vendor目錄下javascript

2:tp5\application\push   新鍵push文件夾,將下載的gatewaywork下的Applications\YourApp裏面的文件拷貝到push下php

3:修改:start_businessworker.phpcss

<?php
/**
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
use \Workerman\Worker;
use \Workerman\WebServer;
use \GatewayWorker\Gateway;
use \GatewayWorker\BusinessWorker;
use \Workerman\Autoloader;html

// 自動加載類
require_once __DIR__ . '/../../vendor/autoload.php';java

// bussinessWorker 進程
$worker = new BusinessWorker();
// worker名稱
$worker->name = 'YourAppBusinessWorker';
// bussinessWorker進程數量
$worker->count = 4;
// 服務註冊地址
$worker->registerAddress = '127.0.0.1:1238';
//設置處理業務的類,此處制定Events的命名空間
//這裏設置,聊天的類的方法,其實就是吧events放到了index模塊下,指定一下而已,也能夠修改到本push下面,本身看着辦
$worker->eventHandler = 'app\index\controller\Events';
// 若是不是在根目錄啓動,則運行runAll方法
if(!defined('GLOBAL_START'))
{
Worker::runAll();
}jquery

 4:修改start_gateway.phpweb

<?php
use \Workerman\Worker;
use \Workerman\WebServer;
use \GatewayWorker\Gateway;
use \GatewayWorker\BusinessWorker;
use \Workerman\Autoloader;json

// 自動加載類
require_once __DIR__ . '/../../vendor/autoload.php';bootstrap

// gateway 進程,這裏使用Text協議,能夠用telnet測試
// 這裏聊天使用websocket協議,若是須要用tcp鏈接,修改websocket爲tcp便可
$gateway = new Gateway("Websocket://0.0.0.0:8282");
// gateway名稱,status方便查看
$gateway->name = 'YourAppGateway';
// gateway進程數
$gateway->count = 4;
// 本機ip,分佈式部署時使用內網ip
$gateway->lanIp = '127.0.0.1';
// 內部通信起始端口,假如$gateway->count=4,起始端口爲4000
// 則通常會使用4000 4001 4002 4003 4個端口做爲內部通信端口
$gateway->startPort = 2900;
// 服務註冊地址
$gateway->registerAddress = '127.0.0.1:1238';瀏覽器

// 心跳間隔
$gateway->pingInterval = 10;
// 心跳數據
$gateway->pingData = '{"type":"ping"}';

/*
// 當客戶端鏈接上來時,設置鏈接的onWebSocketConnect,即在websocket握手時的回調
$gateway->onConnect = function($connection)
{
$connection->onWebSocketConnect = function($connection , $http_header)
{
// 能夠在這裏判斷鏈接來源是否合法,不合法就關掉鏈接
// $_SERVER['HTTP_ORIGIN']標識來自哪一個站點的頁面發起的websocket連接
if($_SERVER['HTTP_ORIGIN'] != 'http://kedou.workerman.net')
{
$connection->close();
}
// onWebSocketConnect 裏面$_GET $_SERVER是可用的
// var_dump($_GET, $_SERVER);
};
};
*/

// 若是不是在根目錄啓動,則運行runAll方法
if(!defined('GLOBAL_START'))
{
Worker::runAll();
}

 5:修改start_register.php

<?php

use \Workerman\Worker;
use \GatewayWorker\Register;

// 自動加載類
require_once __DIR__ . '/../../vendor/autoload.php';

// register 必須是text協議
$register = new Register('text://0.0.0.0:1238');

// 若是不是在根目錄啓動,則運行runAll方法
if(!defined('GLOBAL_START'))
{
Worker::runAll();
}

 6:將events放到index模塊的controller下

<?php
namespace app\index\controller

/**

* 聲明:這裏是處理業務邏輯的,跟聊天頁面對應的東西,關聯本頁面是在push下的start_BusinessWorker這個文件裏綁定引入到這裏的
* 用於檢測業務代碼死循環或者長時間阻塞等問題
* 若是發現業務卡死,能夠將下面declare打開(去掉//註釋),並執行php start.php reload
* 而後觀察一段時間workerman.log看是否有process_timeout異常
*/
//declare(ticks=1);

/**
* 聊天主邏輯
* 主要是處理 onMessage onClose
*/
use \GatewayWorker\Lib\Gateway;

class Events
{
/**
* 有消息時
* @param int $client_id
* @param mixed $message
*/
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));
}
}

}

7:index模塊下新建view\index\index.html

<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>workerman-chat PHP聊天室 Websocket(HTLM5/Flash)+PHP多進程socket實時推送技術</title>
<script type="text/javascript">
//WebSocket = null;
</script>
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
<link href="/static/css/style.css" rel="stylesheet">
<!-- Include these three JS files: -->
<script type="text/javascript" src="/static/js/swfobject.js"></script>
<script type="text/javascript" src="/static/js/web_socket.js"></script>
<script type="text/javascript" src="/static/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/swf/WebSocketMain.swf";
// 開啓flash的websocket debug
WEB_SOCKET_DEBUG = true;

var ws, name, client_list={};

// 鏈接服務端
function connect() {
// 建立websocket
ws = new WebSocket("ws://"+document.domain+":8282");
//console.log(ws);
// 當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="http://workerman.net:8383" target="_blank"><img style="width:252px;margin-left:5px;" src="/img/workerman-todpole.png"></a>
</div>
</div>
</div>
</body>
</html>

8:start_for_win.bat

php application\push\start_register.php application\push\start_gateway.php application\push\start_businessworker.phpPause

相關文章
相關標籤/搜索