TP5 GatewayWorker 及时聊天

TP5 GatewayWorker 及时聊天

借鉴 https://www.cnblogs.com/wt645631686/p/7366924.html

1 安装tp5框架
2 去官网下载gateway-worker,里面有demo。http://www.workerman.net/download
TP5 GatewayWorker 及时聊天插图
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 GatewayWorker 及时聊天插图(1)
运行成功

小项目

简单的优化了下
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

可实现即时对话功能

没有账号? 忘记密码?

社交账号快速登录