0

0

workerman怎么实现分组群聊

爱喝马黛茶的安东尼

爱喝马黛茶的安东尼

发布时间:2019-12-12 09:31:25

|

6667人浏览过

|

来源于php中文网

原创

workerman怎么实现分组群聊

一、基础

1. workerman

workerman是国人开发的良心高性能的PHP socket 服务器框架,在全球最大同性交友平台gayHub的star都4K多,可以想象是多么的牛X。

可以单独部署,也可以整合进MVC的框架(TP,laravel等),可以说非常实用,并发效果也好。

官网地址:

http://www.workerman.net/workerman

gayhub地址:

https://github.com/walkor/workerman/

2. gateway-worker

gateway-worker(后面直接称gateway)是基于 workerman开发的TCP长连接框架,用于快速开发TCP长连接应用。

在线聊天一般都是实用长连接保持通信,使用 workerman虽然能够做到同样的效果,但是gateway更加的方便快捷。

(轮询构建的聊天室已经OUT了,实在是太...)

gayhub地址:

https://github.com/walkor/GatewayWorker

3. gatewayClient

gateClient是用来辅助 workerman或者是gateway进行用户分组以及向用户发送信息的组件,同时,能够快速便捷的将原有系统的uid和clientid绑定起来。

gayhub地址:

https://github.com/walkor/GatewayClient

二、理论:

1. 与MVC系统整合的原则:

·现有mvc框架项目与GatewayWorker独立部署互不干扰;

·所有的业务逻辑都由网站页面post/get到mvc框架中完成;

·GatewayWorker不接受客户端发来的数据,即GatewayWorker不处理任何业务逻辑,GatewayWorker仅仅当做一个单向的推送通道;

·仅当mvc框架需要向浏览器主动推送数据时才在mvc框架中调用Gateway的API(GatewayClient)完成推送。

2. 实现步骤:

(1)网站页面建立与GatewayWorker的websocket连接;

(2)GatewayWorker发现有页面发起连接时,将对应连接的client_id发给网站页面;

(3)网站页面收到client_id后触发一个ajax请求(假设是bind.php)将client_id发到mvc后端;

(4)mvc后端bind.php收到client_id后利用GatewayClient调用Gateway::bindUid($client_id, $uid)将client_id与当前uid(用户id或者客户端唯一标识)绑定。如果有群组、群发功能,也可以利用Gateway::joinGroup($client_id, $group_id)将client_id加入到对应分组;

(5)页面发起的所有请求都直接post/get到mvc框架统一处理,包括发送消息;

(6)mvc框架处理业务过程中需要向某个uid或者某个群组发送数据时,直接调用GatewayClient的接口Gateway::sendToUid Gateway::sendToGroup 等发送即可。

BlackBox AI
BlackBox AI

AI编程助手,智能对话问答助手

下载

三、实现—配置和开启Gateway:

1.下载和使用gateway

可以单独使用,也可以放在框架的public目录下。

2.编辑start.php

·start.php是需要使用php命令行运行的。

·注意require_once的路径

ini_set('display_errors', 'on');
use Workerman\Worker;
if(strpos(strtolower(PHP_OS), 'win') === 0)
{
    exit("start.php not support windows, please use start_for_win.bat\n");
}
// 检查扩展
if(!extension_loaded('pcntl'))
{
    exit("Please install pcntl extension.See http://doc3.workerman.net/appendices/install-extension.html\n");
}
if(!extension_loaded('posix'))
{
    exit("Please install posix extension.See http://doc3.workerman.net/appendices/install-extension.html\n");
}
// 标记是全局启动
define('GLOBAL_START', 1);
// 注意这里的路径
require_once '../vendor/autoload.php';
// 加载所有Applications/*/start.php,以便启动所有服务
foreach(glob(__DIR__.'/Applications/*/start*.php') as $start_file)
{
    require_once $start_file;
}
// 运行所有服务
Worker::runAll();

3. start_gateway.php

·在ApplicationsYourAppstart_gateway.php中可以编辑

// 部分文件内容
//将$gateway改成websocket协议,demo中是text协议
$gateway = new Gateway("websocket://0.0.0.0:8282");

4.start_register.php

·需要注意start_register.php 中$register必须是text协议,同时需要注意端口

// register 服务必须是text协议
$register = new Register('text://192.168.124124.125:1238');

5. 配置好后,开启start.php

$ php start.php start

四、实现-服务端开发

上面提到了,用户只有在触发连接的时候才经过gateway的onConnect($client_id),而所有的业务操作都应该在web系统中实现。

因此我创建了一个GatewatServer.php的controller,负责处理这些业务

post('room')));
        $clientId=trimAll($request->post('client_id'));
        // 接受到上面的三个参数,进行分组操作
        Gateway::$registerAddress = '192.168.124124.125:1238';
        // client_id与uid绑定
        // Gateway::bindUid($clientId, $userGuid);
        // 加入某个群组(可调用多次加入多个群组) 将clientid加入roomid分组中
        Gateway::joinGroup($clientId, $roomId);
        // 返回ajax json信息
        $dataArr=[
            'code'=>$userGuid,
            'status'=>true,
            'message'=>'Group Success'
        ];
        return json()->data($dataArr);
    }
    // 接受用户的信息 并且发送
    public function send(Request $request){
        Gateway::$registerAddress = '192.168.124124.125:1238';
        // 获得数据
        $userGuid=Session::get('loginuser');
        $roomId=intval(trimAll($request->post('room')));
        $message=trim($request->post('message'));
        // 获得用户的称呼
        $userInfo=Cache::get($userGuid);
        // 将用户的昵称以及用户的message进行拼接
        $nickname=$userInfo['nickname'];
        $message=$nickname." : ".$message;
        // 发送信息应当发送json数据,同时应该返回发送的用户的guid,用于客户端进行判断使用
        $dataArr=json_encode(array(
            'message' => $message,
            'user'=>$userGuid
        ));
        // 向roomId的分组发送数据
        Gateway::sendToGroup($roomId,$dataArr);
    }
}

五、实现-客户端连接与发送/接收:

开启了gateway之后,就可以监听并且等待浏览器接入了。

客户端这里使用js监听websocket:

1. 用于处理客户端连接websocket以及接收消息

// 这个示例和gateway官网的示例是一样的
    // 监听端口
    ws = new WebSocket("ws://192.168.124124.125:8282");
    // 绑定分组的ajaxURL
    var ajaxUrl="{:url('/gateway/bind')}";
    // 发送消息的ajaxURL
    var ajaxMsgUrl="{:url('/gateway/send')}";
    // 通过房间号进行分组
    var roomId="{$roomInfo.guid}";
    // 获取当前登录用户的guid,用于标识是自己发送的信息
    var loginUser="{$userLoginInfo.guid}";
    // 获取当前房间号的主播的uid,用于标识是主播发送的信息
    var roomUser="{$roomInfo.uid}";
    // 服务端主动推送消息时会触发这里的onmessage
    ws.onmessage = function(e){
        // console.log(e.data);
        // json数据转换成js对象
        var data = eval("("+e.data+")");
        var type = data.type || '';
        switch(type){
            // Events.php中返回的init类型的消息,将client_id发给后台进行uid绑定
            case 'init':
                // 利用jquery发起ajax请求,将client_id发给后端进行uid绑定
                $.post(ajaxUrl, {client_id: data.client_id,room:roomId}, function(data){
                    // console.log(data);
                }, 'json');
                break;
            // 当mvc框架调用GatewayClient发消息时直接alert出来
            default :
                // 如果登陆用户的guid和数据发送者的guid一样,则使用不同的颜色(只能自己看到)
                if(loginUser == data.user){
                    addMsgToHtml(data.message,'#F37B1D');
                    break;
                // 如果发送者的guid和主播uid一样,则对所有的显示都增加一个[主播标识]
                }else if(data.user==roomUser){
                    addMsgToHtml("[主播] "+data.message,'#0e90d2');
                    break;
                }else{
                // 其他的就正常发送消息
                    addMsgToHtml(data.message,'#333');
                }
                break;
        }
    };

2. 用于将接收到的消息添加到div中进行显示

// 向面板中增加新接收到的消息
    // 其中message是消息,color是显示的颜色,主要为了区分主播以及自己发送的消息和系统提示
    function addMsgToHtml(message,color) {
        if(message.length==0){
            return false;
        }
        // 获取html,并且增加html
        var obj=$("#room-viedo-chat");
        var html=obj.html();
        // 
        html+='

'+message+'

'; obj.html(html); // 将滚动条滚动到底部 obj.scrollTop(obj[0].scrollHeight); }

3.用于发送消息

// 发送聊天消息
    function sendMsg(){
        // 去掉onclick属性,使得3秒之内无法发送信息
        $("#sendMsgBox").attr('onclick','');
        var btnObj=$("#sendMsgBtn");
        var tmpNum=3;
        var tmpMsg=tmpNum+' S';
        btnObj.text(tmpMsg);
        var int =setInterval(function () {
            // 3秒之内不能发送信息,3秒之后,回复onclick属性以及文字
            if(tmpNum==0){
                tmpMsg="发送";
                clearInterval(int);
                btnObj.text("发送");
                $("#sendMsgBox").attr('onclick','sendMsg()');
            }
            btnObj.text(tmpMsg);
            tmpNum-=1;
            tmpMsg=tmpNum+' S';
        },1000);
        var message=$("#chattext").val().trim();
        var obj=$("#room-viedo-chat");
        var html=obj.html();
        if(message.length>=140){
            // 获取html,并且增加html
            addMsgToHtml("系统提示: 不能超过140个字符","#8b0000");
            return false;
        }
        if(message.length==0){
            // 获取html,并且增加html
            addMsgToHtml("系统提示: 不能发送空消息","#8b0000");
            return false;
        }
        // 向server端发送ajax请求
        $.post(ajaxMsgUrl,{room:roomId,message:message},function (data) {
        },'json');
        return false;
    }

4.一点儿html代码


    
发送

六、效果:

效果很明显:

·系统提示是单独的颜色

·本人发布的,是自己能够分辨的橙色

·主播发布的是蓝色,同时前面有[主播]标识

·看其他人发布的就是普通的颜色

1576113301681338.png

PHP中文网,有大量免费的workerman入门教程,欢迎大家学习!

相关专题

更多
Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

8

2026.01.15

公务员递补名单公布时间 公务员递补要求
公务员递补名单公布时间 公务员递补要求

公务员递补名单公布时间不固定,通常在面试前,由招录单位(如国家知识产权局、海关等)发布,依据是原入围考生放弃资格,会按笔试成绩从高到低递补,递补考生需按公告要求限时确认并提交材料,及时参加面试/体检等后续环节。要求核心是按招录单位公告及时响应、提交材料(确认书、资格复审材料)并准时参加面试。

44

2026.01.15

公务员调剂条件 2026调剂公告时间
公务员调剂条件 2026调剂公告时间

(一)符合拟调剂职位所要求的资格条件。 (二)公共科目笔试成绩同时达到拟调剂职位和原报考职位的合格分数线,且考试类别相同。 拟调剂职位设置了专业科目笔试条件的,专业科目笔试成绩还须同时达到合格分数线,且考试类别相同。 (三)未进入原报考职位面试人员名单。

58

2026.01.15

国考成绩查询入口 国考分数公布时间2026
国考成绩查询入口 国考分数公布时间2026

笔试成绩查询入口已开通,考生可登录国家公务员局中央机关及其直属机构2026年度考试录用公务员专题网站http://bm.scs.gov.cn/pp/gkweb/core/web/ui/business/examResult/written_result.html,查询笔试成绩和合格分数线,点击“笔试成绩查询”按钮,凭借身份证及准考证进行查询。

11

2026.01.15

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

65

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

36

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

75

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

21

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

35

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号