GatewayWorker聊天室实践

特别注意:

[1]客户端的事件及数据全部由Gateway转发给BusinessWorker处理,BusinessWorker默认调用Events.php中的onConnect onMessage onClose处理业务逻辑。

[2]通过GatewayClient发送的数据不会经过Event.php,而是直接经由Gateway进程转发给客户端。GatewayClient无法接收客户端发来的数据。

第一步准备好最新的TP5和GatewayWorker
https://www.workerman.net/download  //GatewayWorker下载地址

http://www.thinkphp.cn/down/1278.html //TP5下载地址

下载完成解压到本地。

GatewayWorker直接放到TP5根目录下就行

下载GatewayClient 

https://github.com/walkor/GatewayClient  //下载地址

因为是最新版的GatewayWorker直接下载最新版的GatewayClient就行,然后解压里面的Gateway.php

放到TP5下的E:\WWW\tp5\thinkphp\library\think这是我的目录,前面要改成自己的目录,注意命名空间。

第二步修改内容
修改刚刚解压的Gateway.php里的内容

namespace GatewayClient; 修改成 

namespace think;

把 注册中心地址改成 public static $registerAddress = '127.0.0.1:9500';

记住后面端口一定要和GatewayWorker\Applications\YourApp下的start_businessworker.php,start_gateway.php,start_register.php保持一致就行,我就改成了9500

start_gateway.php文件,这个文件是默认的文件,默认协议是text协议

 

修改GatewayWorker\Applications\YourApp下的start_gateway.php

$gateway = new Gateway("tcp://0.0.0.0:8282");
修改成
$gateway = new Gateway("websocket://0.0.0.0:8282");

第三步创建控制器
话不多说直接贴上控制器代码

<?php
namespace app\base\controller\v1;
use app\base\controller\v1\Base as Base;
use think\Controller;
use think\Gateway;

class WorkerMan extends Controller
{

	public function bind() {
		$uid = 3;
		$client_id = input('client_id');
 
		$gateway = new Gateway();
 
		$gateway->bindUid($client_id, $uid);
		$message = '绑定成功' . $uid . '-' . $client_id;
		$gateway->sendToUid($uid,$message);
	}
 
 	public function message() {
		$to_uid = input('uid');
		$message = input('msg');
		$gateway = new Gateway();
		$data['msg'] = $message;
		$data['from_uid'] = 3;
		$data['to_uid'] = $to_uid;
//         $gateway->sendToUid($to_uid, json_encode($data)); //发给对方
		$gateway->sendToAll(json_encode($data));//发给所有人
//        $gateway->sendToUid($data['from_uid'], json_encode($data)); //发给自己
		echo json_encode($data);
	}
}


新建index.html,代码如下

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <title>chatroom</title>
    <script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"/></script>
 
    <script type="text/javascript">
    // 打开一个 web socket
    var ws = new WebSocket("ws://8.131.90.126:8282");
    // var ws = new WebSocket("ws://8.140.115.226:2000");
    ws.onopen = function ()
    {
        // var name = prompt("请输入昵称","");
        // if(name){
        //     $("b").text(name);
        // }
        console.log('上线');
    };
    ws.onerror=function(e){
        console.log(e);
    }
    ws.onclose=function(e){
        console.log(e);
        console.log('下线');
    }
    ws.onmessage = function (evt)
    {
        var received_msg = evt.data;
        // console.log("数据已接收..." + received_msg);
        if(isJsonString(received_msg)){
            var jmsg = JSON.parse(received_msg);
			console.log(jmsg);
        	switch (jmsg.type) {
				case 'init':
					var bind = '{"type":"bind","from_id":"' + 1 + '","to_id":"' + 2 + '"}';
					ws.send(bind);
					var online = '{"type":"online","from_id":"' + 1 + '","to_id":"' + 2 + '"}';
					ws.send(online);
					break;
				// case 'online':
				// 	if (jmsg.status == 1) {
				// 		var say = '{"type":"say","from_id":"' + 1 + '","to_id":"' + 2 + '"}';
				// 		ws.send(say);
				// 		// set_online_status(true);
				// 	} else {
				// 		// set_online_status(false);
				// 	}
				// 	return;
				// case "say":
				// 	// To_receive_message('txt',message);
				// 	// $(".chat-content").scrollTop(3000);
				// 	return;
			}
        }
    }
 
    function isJsonString(str) {
        try {
            if (typeof JSON.parse(str) == "object") {
                return true;
            }
        } catch (e) {
        }
        return false;
    }
	
	function send() {
		var message = document.getElementById('text').value;
		ws.send(message);
	}
    </script>
</head>
<body>
<ul id="message">
 
</ul>
 
<div>
    <label>昵称:<b></b></label><br/>
    <input name="msg" value="" size="50">
    <button type="button" id="send" >发送</button>
</div>

<!-- <script>
//后台交互式
    $(function () {
        $url = "http://8.131.90.126:8083/public/base/v1/message"
        $("#send").click(function () {
            var name = $("b").html();
            var msg = $('input[name="msg"]').val();
            $.post($url, {from_uid: 2, msg: msg,to_uid:1}, function (data) {
                console.log(data);
                $('input[name="msg"]').val('');
            });
 
        });
    });
</script> -->

<script type="text/javascript">
	//websocket交互式
	$("#send").click(function () {
	    var msg = $('input[name="msg"]').val();
	    // $.post($url, {from_uid: 2, msg: msg,to_uid:1}, function (data) {
		var say = '{"type":"say","from_id":"' + 1 + '","to_id":"' + 2 + '","content":"'+msg+'"}';
		ws.send(say);
	        // $('input[name="msg"]').val('');
	 
	});
</script>
</body>
</html>

然后在本地服务器开启GatewayWorker

windows双击打开GatewayWorker\start_for_win.bat

linux在GatewayWorker目录下执行php start.php start  运行(注意安全组需要放行端口  目前我放行的8282  9500 )

打开浏览器输入网址加上Uid

出现绑定成功说明已经成功了,然后第一个输入框输入对应id就能和这个id的人对话了

 Eents.php示例

<?php
/**
 * This file is part of workerman.
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the MIT-LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @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
 */

/**
 * 用于检测业务代码死循环或者长时间阻塞等问题
 * 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload
 * 然后观察一段时间workerman.log看是否有process_timeout异常
 */
//declare(ticks=1);

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, json_encode(['type'=>'init','client_id'=>$client_id]));
        // 向所有人发送
//        Gateway::sendToAll("$client_id login\r\n");
    }
    
   /**
    * 当客户端发来消息时触发
    * GatewayWorker建议不做任何业务逻辑,onMessage留空即可
    * @param int $client_id 连接id
    * @param mixed $message 具体消息
    */
   public static function onMessage($client_id, $message)
   {
       //示例: $message = '{"type":"send_to_uid","uid":"xxxxx", "message":"...."}'
       $message_data = json_decode($message,true);
       if ($message_data){
           //TODO 方便区分信息传递类型
           $type = $message_data['type'];
           // 发送人ID,此处为数据库中管理员的ID
           $from_id = $message_data['from_id'];
           // 接收人ID
           $to_id = isset($message_data['to_id'])?$message_data['to_id']:0;
           switch ($type){
               case 'bind':
                   //将client_id与uid绑定,用来唯一确定一个客户端用户或者设备
                   Gateway::bindUid($client_id,$from_id);
                   $_SESSION['gateway-worker_'.$client_id] = $from_id;
                   return;
               case 'online':
                   //判断接收人是否在线
                   $onlineStatusForTo_id = Gateway::isUidOnline($to_id);
                   $onlineStatusForFrom_id = Gateway::isUidOnline($from_id);
                   Gateway::sendToUid($from_id, json_encode(['type'=>'online','to_id'=>$to_id,'status'=>$onlineStatusForTo_id]));
                   Gateway::sendToUid($to_id, json_encode(['type'=>'online','to_id'=>$from_id,'status'=>$onlineStatusForFrom_id]));
                   return;
               case 'say':
                   //发送文字
                   $text = nl2br(htmlspecialchars($message_data['content']));
                   $sayData = [
                       'type' => 'say',
                       'content' => $text,
                       'from_id' => $from_id,
                       'to_id' => $to_id
                   ];
                   if (Gateway::isUidOnline($to_id)){
                       $sayData['is_read'] = 1;
                       Gateway::sendToUid($to_id, json_encode($sayData));
                   }else{
                       $sayData['is_read'] = 0;
                   }
                   Gateway::sendToUid($from_id,json_encode($sayData));
                   return;
           }
       }else{
           return;
       }
   }
   
   /**
    * 当用户断开连接时触发
    * @param int $client_id 连接id
    */
   public static function onClose($client_id)
   {
       $uid = $_SESSION['gateway-worker_'.$client_id];
       // 向所有人发送
       $send_msg = json_encode(['type'=>'online','to_id'=>$uid,'status'=>0,'content'=>'对方掉线了!']);
       $_SESSION['gateway-worker_'.$client_id] = null;
//       Gateway::sendToAll($send_msg);
   }
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值