TP5 GatewayWorker 及时聊天
借鉴 https://www.cnblogs.com/wt645631686/p/7366924.html
Gateway手册 https://www.kancloud.cn/walkor/gateway-worker/390865
流程可以看这个 和 tp5结合更详细的流程
https://www.thinkphp.cn/code/3937.html
1 安装tp5框架
2 去官网下载gateway-worker,里面有demo。http://www.workerman.net/download
3 tp5/application 新建 push 文件夹
将下载的压缩包解压,将Applications/Yourapp中的文件全部复制到tp5/application/push 下
修改start_gateway.php
$gateway = new Gateway("tcp://0.0.0.0:8282");
改为
$gateway = new Gateway("websocket://0.0.0.0:8282");
将vendor/workerman的全部文件复制到 tp5/vendor/workerman 下
4 修改 tp5/vendor/composer/autoload_static.php
$prefixLengthsPsr4
加入
'W' =>
array (
'Workerman\\' => 10,
),
'G' =>
array (
'GatewayWorker\\' => 14,
),
$prefixDirsPsr4
'Workerman\\' =>
array (
0 => __DIR__ . '/..' . '/workerman/workerman',
),
'GatewayWorker\\' =>
array (
0 => __DIR__ . '/..' . '/workerman/gateway-worker/src',
),
windows
5 将解压后的文件夹中的start_for_win.bat复制到thinkphp5的根目录,即与application同级的目录
6 右键start_for_win.bat,点编辑,将里面的目录改成自己的目录,这里改为
php application\push\start_register.php application\push\start_gateway.php application\push\start_businessworker.php
Pause
7 保存退出。双击运行
linux
5 将解压后的文件夹中的start.php复制到thinkphp5的根目录,即与application同级的目录。
6 将start.php文件中最后部分forearch循环括号内的路径改为自己的正确路径。
7 在命令行php start.php start 启动。
运行成功
小项目
简单的优化了下
Tp5\application\push\Events.php
<?php
use \GatewayWorker\Lib\Gateway;
/**
* 主逻辑
* 主要是处理 onConnect onMessage onClose 三个方法
* onConnect 和 onClose 如果不需要可以不用实现并删除
*/
class Events
{
/**
* 当客户端连接时触发
* 如果业务不需此回调可以删除onConnect
*
* @param int $client_id 连接id
*/
public static function onConnect($client_id)
{
/*
// 向当前client_id发送数据
Gateway::sendToClient($client_id, "Hello $client_id\r\n");
// 向所有人发送
Gateway::sendToAll("$client_id login\r\n");
*/
// 发送init请求;
Gateway::sendToClient($client_id,json_encode([
'type'=>'init',
'client_id'=>$client_id
]));
// 向所有人发送
$content = nl2br(htmlspecialchars("login"));
$data=[
'type'=>'notice',
'content'=>$content,
'create_time'=> date('Y-m-d H:i:s')
];
GateWay::sendToAll(json_encode($data));
}
/**
* 当客户端发来消息时触发
* @param int $client_id 连接id
* @param mixed $message 具体消息
*/
public static function onMessage($client_id, $message)
{
// 向所有人发送
//Gateway::sendToAll("$client_id said $message\r\n");
$req_data = json_decode($message,true);
switch ($req_data['type']){
// id绑定
case "bind":
Gateway::bindUid($client_id, $req_data['from_uid']);
Gateway::sendToUid($req_data['from_uid'], json_encode(["type"=>"bind","data"=>"success to bind!!"]));
break;
// 文本消息
case 'text':
$content = nl2br(htmlspecialchars($req_data['data']));
$data=[
'type'=>'text',
'content'=>$content,
'from_uid'=>$req_data['from_uid'],
'to_uid'=>$req_data['to_uid'],
'create_time'=> date('Y-m-d H:i:s')
];
Gateway::sendToUid($req_data['to_uid'], json_encode($data));
break;
}
}
/**
* 当用户断开连接时触发
* @param int $client_id 连接id
*/
public static function onClose($client_id)
{
// 向所有人发送
$content = nl2br(htmlspecialchars("logout"));
$data=[
'type'=>'notice',
'content'=>$content,
'create_time'=> date('Y-m-d H:i:s')
];
GateWay::sendToAll(json_encode($data));
}
}
前端样式
hah.php
放至thinkphp5的根目录,即与application同级的目录
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
</head>
<script src="../js/jquery-1.7.2.min.js"></script>
<!-- http://127.0.0.1/tp5/hah.php?from_uid=2&to_uid=1 -->
<!-- http://127.0.0.1/tp5/hah.php?from_uid=1&to_uid=2 -->
<script>
// 左侧追加
function leftAppend(text)
{
leftHtml = "";
leftHtml += '<div class="itemMessage itemLeft">';
leftHtml += '<div class="TopImg"></div>'+text;
leftHtml += '</div>';
htmlAppend(leftHtml);
}
//右侧追加
function rightAppend(text)
{
rightHtml = "";
rightHtml += '<div class="itemMessage itemRight">';
rightHtml += '<div class="TopImg"></div>'+text;
rightHtml += '</div>';
htmlAppend(rightHtml);
}
function htmlAppend(html)
{
$(".messageBox .messageContent").append(html);
//$(".messageBox").scrollTop($(".messageContent").height(),200);
scrollTime = 100;
$(".messageBox").animate({scrollTop:$(".messageContent").height()},scrollTime);
}
$(function(){
// 当前登录的 uid
var from_uid = "<?php echo $_GET['from_uid']; ?>";
var to_uid = "<?php echo $_GET['to_uid']; ?>";
var ws = new WebSocket("ws://127.0.0.1:8282");
ws.onopen = handleSend;
ws.onmessage = handleMessage;
ws.onclose = handleClose;
ws.onerror = handleError;
function handleMessage(e)
{
var message = eval("("+e.data+")");
switch (message.type){
case 'init':
console.log("连接成功:",message);
var bind = '{"type":"bind","from_uid":"'+from_uid+'"}';
ws.send(bind);
return;
case "bind":
console.log("绑定成功:",message)
return;
case "text":
console.log("收到新消息:",message)
leftAppend(message['content']);
return;
case "notice":
if(message.content == "login")
console.log(":",message)
else if(message.content == "logout")
console.log("通知消息:",message)
else
console.log("通知消息:",message)
return;
default:
console.log("其他消息:",message)
//leftAppend(message['content']);
return;
}
}
function handleSend()
{
console.log("连接已打开...");
}
// 处理后台服务连接关闭事件
function handleClose()
{
console.log("连接已关闭...");
}
// 处理WebSocket错误
function handleError()
{
console.log("WebSocketError!");
}
// 点击发送
$(".send-btn").click(function(){
messageSend();
})
$(document).keydown(function(event){
keyboard = event.keyCode;
if(keyboard == 13)
messageSend();
});
function messageSend()
{
var content = $(".content").val();
var message = '{"data":"'+content+'","type":"text","from_uid":"'+from_uid+'","to_uid":"'+to_uid+'"}';
console.log(message);
rightAppend(content);
ws.send(message);
}
})
</script>
<style>
*{ margin:0; padding:0; font-size:12px;}
.box{ border:2px solid #999; min-height:400px; border-radius: 10px; margin:0 auto; width:230px; overflow:hidden;}
.mbBox{ position:relative; padding-bottom:30px;}
.mbBox .messageBox{ height:370px;margin:5px 3px;overflow: auto;}
.TopImg{ width:20px; height:20px; background:blue;}
.itemLeft .TopImg{ margin-right:5px;}
.itemRight .TopImg{ margin-left:5px;}
.itemMessage {
display: flex;
margin-bottom: 5px;
}
.itemLeft {flex-direction: row;}
.itemRight { flex-direction: row-reverse;}
.mbBox .sendBox{ position:absolute; bottom:0px; width:100%; border:1px #CCC solid;padding: 1px; background:#CCC;}
.sendBox .content{ line-height:30px; width:100%; border:0;width: calc(100% - 50px);padding-left: 5px;}
.sendBox .send-btn{ position:absolute; padding:10px; right:0px; top:50%; transform: translate(0px, -50%); cursor:pointer;}
/*滚动条整体样式*/
.messageBox::-webkit-scrollbar {
width : 3px;
}
/*滚动条里面小方块*/
.messageBox::-webkit-scrollbar-thumb {
border-radius: 10px;
box-shadow : 0 0 5px rgba(0, 0, 0,0.2);
background : #535353;
}
/*滚动条里面轨道*/
.messageBox::-webkit-scrollbar-track {
box-shadow : inset 0 0 5px rgba(0, 0, 0, 0.2);
border-radius: 10px;
background : #ededed;
}
</style>
<div class="box">
<div class="mbBox">
<div class="messageBox">
<div class="messageContent">
<div class="itemMessage itemLeft">
<div class="TopImg"></div>今天天气真好
</div>
<div class="itemMessage itemRight">
<div class="TopImg"></div>是的嘛
</div>
</div>
</div>
<div class="sendBox">
<input class="content" value="hello world!!">
<span class="send-btn">发送</span>
</div>
</div>
</div>
<body>
</body>
</html>
运行
http://127.0.0.1/tp5/hah.php?from_uid=2&to_uid=1
http://127.0.0.1/tp5/hah.php?from_uid=1&to_uid=2
可实现即时对话功能