workman进阶应用 GatewayWorker 仿微信 做聊天室

发布于:2025-05-14 ⋅ 阅读:(11) ⋅ 点赞:(0)

聊天室主要用到GatewayWorker  ,它是对workerman的进一步封装

GatewayWorker基于Workerman开发的一个项目框架,用于快速开发TCP长连接应用,例如app推送服务端、即时IM服务端、物联网、智能家居等等。

1.  安装环境

1.1 首先下载框架

composer require workerman/gateway-worker

然后下载 demo

GatewayWorker 有分为linux版本 和 windows 版本。

2个版本主要不同是 :

1. 启动文件不同 , windows 用 bat 文件启动  ,linux 直接 php start.php start 启动 

以后台进程的形式开启

php start.php start -d

2. 某些文件夹的命名不一样 

由于我是windows开发,运行在linux服务器 。这里我这里直接选择linux版本的  , 然后启动文件我复制windows版的bat启动文件

我用的是tp5  我把启动文件放到根目录  调整bat里面的路径

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

1.2 第二步

将Applications/Yourapp复制到tp5目录application中,并更改名字为push(这里随意)

|--push
  |--Events.php
  |--start_businessworker.php
  |--start_gateway.php
  |--start_register.php

将start.php复制到tp5根目录下,并更改start.php最后的foreach路径   我的目录是application/push

foreach(glob(__DIR__.'/application/push/start*.php') as $start_file)
{
    require_once $start_file;
}

根目录中启动 php start.php start  (linux)  ,windows 直接 双击 bat文件  start_for_win

2. 如何使用gatewayworker

一般即时通讯的业务逻辑 会写在在  Events.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");
    }
    
   /**
    * 当客户端发来消息时触发
    * @param int $client_id 连接id
    * @param mixed $message 具体消息
    */
   public static function onMessage($client_id, $message)
   {
        // 向所有人发送 
        Gateway::sendToAll("$client_id said $message\r\n");
   }


}

  点对点的通讯 就是类似下图


2.1 常用函数和思路

1. bindUid    跟客户端传入的 uid 绑定

2.  isUidOnline    判断该客户端id 是否在线

3.  sendToUid   发消息给指定客户端id

4.  sendToAll    向所有连接到 该socket服务器的客户端 发送消息

3. 简单例子

服务器端:

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");
		Gateway::sendToClient($client_id, json_encode(["type"=>'init','client_id'=>$client_id]));
    }
    
   /**
    * 当客户端发来消息时触发
    * @param int $client_id 连接id
    * @param mixed $message 具体消息
    */
   public static function onMessage($client_id, $message)
   {
        // 向所有人发送 
		$message_data = json_decode($message,true);
		
		if(!$message_data){
			return;
		}
		
		switch($message_data['type']){
			case 'bind':
				//$datas = ['type'=>'text','client_id'=>$client_id,'data'=>$message_data['data']];
				//echo $message_data['fromid'];
				Gateway::bindUid($client_id, $message_data['fromid']);
				break;
			case 'talk':
				
				$datas = [
					'type'=>'text',
					'client_id'=>$client_id,
					'data'=>htmlspecialchars($message_data['data']),
					'fromid'=>$message_data['fromid'],
					'toid'=>$message_data['toid'],
					'timestamp'=>time()
				];
				
				if(Gateway::isUidOnline($message_data['toid'])){
					$datas['isread']=1;	
				}else{
					$datas['isread']=0;	
				}
				Gateway::sendToUid($message_data['toid'],json_encode($datas));
				//保存数据
				$talkurl='http://www.superchat.com/index/Chat';
				$params =['fromid'=>$message_data['fromid'],'toid'=>$message_data['toid'],'content'=>htmlspecialchars($message_data['data']),'time'=>time(),'isread'=>$datas['isread'],'type'=>1];
				self::curl_https($talkurl,$params,1);
				
				//同步数据
				Gateway::sendToUid($message_data['fromid'],json_encode(['type'=>'update_message','client_id'=>$client_id,'fromid'=>$message_data['fromid'],'toid'=>$message_data['toid'],'timestamp'=>time()]));
				
				break;
			case 'online':
				$datas = ['type'=>'online','fromid'=>$message_data['fromid'],'toid'=>$message_data['toid']];
				
				$datas['isonline'] = 0;	
				
				Gateway::sendToUid($message_data['fromid'],json_encode($datas));
				break;
			case 'images':
				$datas = [
					'type'=>'images',
					'fromid'=>$message_data['fromid'],
					'toid'=>$message_data['toid'],
					'data'=>$message_data['data'],
					'time'=>time()
				];
				Gateway::sendToUid($message_data['toid'],json_encode($datas));
				break;
			default:
			
		}
		
		//echo '123123';
        
   }

}

客户端:

<script>
var API = "http://www.superchat.com/index/Chat/";
var fromid ={$fromid};

var ws = new WebSocket("ws://127.0.0.1:8282");
ws.onmessage = function(e) {
    var Respoonse = JSON.parse(e.data);
    console.log(Respoonse);
    switch(Respoonse.type){
        case 'init':
            //console.log(Respoonse);
            var bindmesaage = '{"type":"bind","fromid":"'+fromid+'"}';
            ws.send(bindmesaage);
            message_list();
            break;

        case 'text':
            $(".fui-content").html('');
            message_list();
            break;	

        case 'images':
            $(".fui-content").html('');
            message_list();
            break;

        case 'update_message':
            $(".fui-content").html('');
            message_list();
            break;

    }


}
</script>

根据 onmessage 返回的json内容  ,对UI 做出相应的更改

4. 参考

tp5.1中gatewayworker简单使用 - L-ran - 博客园