PHP+Laravel5.8+GatewayWorker实现即时文字聊天,文件互传功能(第二篇:GatewayWorker基类的配置与部署)

第二篇:GatewayWorker基类的配置与部署

本章节将演示:
1.代码的在服务器的部署过程
2.前端是如何将消息发送给后台的并进行处理的。

php端部署

1.上一章节我讲过,这个项目分为3端(客户端、通信端、服务端),他们的设计思路我在这里再次明确一下。
客户端(前端H5页面):负责展示和发送用户之间往来的消息内容。
通信端:负责接受和发送用户的消息内容。
服务端:负责处理发送消息和接收消息的业务逻辑等(如用户的聊天记录存入数据库、用户消息的撤回、用户发送违规图片的审核等一些功能,我们都在这里完成)。

2.前面章节我们在workerman->GatewayWorker手册官网下载的Linux系统快速开始的Demo
现在我把他复制到项目中的根目录中来。目录如下图所示:
在这里插入图片描述
3.开始填写配置(在配置之前请开发者一定先阅读手册一下内容,这很重要,因为后面有些坑都在这里)GatewayWorker->开发必读
现在打开 项目名\GatewayWorker\Applications\YourApp\start_gateway.php
根据你的业务需求修改 设置Gateway的协议为websocket因为H5客户端要用这个协议进行通讯。
我的域名有https证书所以我修改了配置项,相关文档请参考官方手册GatewayWorker手册->创建wss服务

$gateway = new Gateway("websocket://0.0.0.0:8282",$context);//这里的8282端口就是上一章节提前在服务器安全组中放行的。这个‘websocket:’协议是H5用的,这里的配置必须和H5前端的配置一致

// 服务注册地址
$gateway->registerAddress = '127.0.0.1:1238';//这个1238端口自己在服务器安全组中放行即可。代码里无需改动。

代码如下:

<?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
 */
use \Workerman\Worker;
use \Workerman\WebServer;
use \GatewayWorker\Gateway;
use \GatewayWorker\BusinessWorker;
use \Workerman\Autoloader;

// 自动加载类
require_once __DIR__ . '/../../vendor/autoload.php';

// gateway 进程,这里使用Text协议,可以用telnet测试
/**
 * https用我
 */
$context = array(
    'ssl' => array(
        'local_cert' => '/www/server/panel/vhost/cert/im_dev.liutong.pro/4539259_im.liutong.pro.pem', // 或者crt文件域名证书以及秘钥文件路径)
        'local_pk' => '/www/server/panel/vhost/cert/im_dev.liutong.pro/4539259_im.liutong.pro.key',//(域名证书以及秘钥文件路径)
        'verify_peer' => false
    )
);
$gateway = new Gateway("websocket://0.0.0.0:8282",$context);//https用这个
// 设置transport开启ssl,websocket+ssl即wss
$gateway->transport = 'ssl';//https用这个

#******  https向上面一样配置  *******  分割线  ******  http向下面$gatewayy一样配置  **************

/**
 * http用我
 */
//$gateway = new Gateway("websocket://0.0.0.0:8282");//http用这个


// gateway名称,status方便查看
$gateway->name = 'YourAppGateway';
// gateway进程数
$gateway->count = 4;
// 本机ip,分布式部署时使用内网ip
$gateway->lanIp = '127.0.0.1';
// 内部通讯起始端口,假如$gateway->count=4,起始端口为4000
// 则一般会使用4000 4001 4002 4003 4个端口作为内部通讯端口 
$gateway->startPort = 2900;
// 服务注册地址
$gateway->registerAddress = '127.0.0.1:1238';

// 心跳间隔(单位:秒,注意这里服务端50s访问前端一次,前端50后返回后端一次,一来一回的时间应为 50s*2 = 100s)
$gateway->pingInterval = 50;
// 心跳数据(标识)
$gateway->pingData = '{"type":"ping"}';

/* 
// 当客户端连接上来时,设置连接的onWebSocketConnect,即在websocket握手时的回调
$gateway->onConnect = function($connection)
{
    $connection->onWebSocketConnect = function($connection , $http_header)
    {
        // 可以在这里判断连接来源是否合法,不合法就关掉连接
        // $_SERVER['HTTP_ORIGIN']标识来自哪个站点的页面发起的websocket链接
        if($_SERVER['HTTP_ORIGIN'] != 'http://kedou.workerman.net')
        {
            $connection->close();
        }
        // onWebSocketConnect 里面$_GET $_SERVER是可用的
        // var_dump($_GET, $_SERVER);
    };
}; 
*/

// 如果不是在根目录启动,则运行runAll方法
if(!defined('GLOBAL_START'))
{
    Worker::runAll();
}


自此你的workerman服务端就配置好了。但是现在还不能用,我们现在开始编写前端代码。

前往Workerman服务端开启socket服务。

1.登录你的阿里云服务器控制台,使用cd命令进入项目根目录中,然后进入GatewayWorker目录中找到start.php使用php命令php start.php start回车看到下图表示服务成功,
参考手册地址:GatewayWorker手册->启动与停止
在这里插入图片描述

前端H5页面编写

1.laravel配置一个路由用来访问呢前端页面。
2.页面的内容我们可以直接从GatewayWorker官方手册->ThinkPHP等框架结合->网站页面js片段中提取
网站页面js片段

{{--即时通讯业务逻辑--}}
<script>
    /**
     * 第一步:与socket建立链接
     * 打开一个 web socket (以下链接方式任选一种即可)
     * 参数解释:var ws = new WebSocket("参数A://参数B:参数C");
     * 参数A:固定写法
     ws:表示http连接
     wss:表示https连接,有https证书的时候使用
     * 参数B:要连接的地址。
     可选参数:127.0.0.1 表示:本地地址
     可选参数:48.662.156.869 表示:你的云服务器的公网ip  (48.662.156.869这个ip是我假设的云服务器公网ip)
     可选参数:im_dev.liutong.pro 表示:这个你的http域名 如(http://im_dev.liutong.pro)
     可选参数:im.liutong.pro 表示:这个是你的https网址域名 如(https://im.liutong.pro)
     * 参数C:端口号
     端口号是可以自定义的(注意取值范围)。记得在服务器->实例安全组中进行放行。
     端口号取值范围:端口不能大于65535,请确认端口没有被其它程序占用,否则启动会报错。如果端口小于1024,需要root权限运行GatewayWorker才能有权限监听,否则报错没有权限。(详情参见手册->《Gateway类的使用》->"初始化"->"ip")
     注意:这里的端口号必须和你在 "项目名\GatewayWorker\Applications\YourApp\start_gateway.php" 中$gateway = new Gateway("websocket://0.0.0.0:8282");这段代码的端口号保持一致。
     */
        // var ws = new WebSocket("ws://127.0.0.1:8282");//进行webSocket的几种方式(方式A:常规操作)
        // var ws = new WebSocket("ws://47.104.249.193:8282");//进行webSocket的几种方式(方式B:使用本机公网ip进行连接)
        // var ws = new WebSocket("ws://im_dev.liutong.pro:8282");//进行webSocket的几种方式(方式C:使用http://im_dev.liutog.pro的方式进行连接)
    var ws = new WebSocket("wss://im.liutong.pro:8282");//进行webSocket的几种方式(方式D:使用HTTPS的方式进行连接,域名:https:im.liutong.pro)

    //第二步:webSocketn事件 open连接建立时触发
    ws.onopen = function() {
        console.log("连接成功");
    };

    //第三步:webSocketn事件 onmessage客户端接收服务端数据时触发
    ws.onmessage = function(evt) {
        //console.log(evt);
        //console.log(evt.data);
        var data = JSON.parse(evt.data);//接受到服务器给我返回的JSON数据并进行解析
        switch(data.type) {//验证链接类型(这个类型中的init值是官方定义的,我们无需改动,后续我们还会自定义一些type值。)
            case 'init'://表示首次链接,GatewayWorker发现有页面发起连接时,将对应连接的client_id发给网站页面
                //进行我方用户id与client_id进行绑定操作,这里我使用ajax请求我方自定义控制器进行处理用户绑定操作
                bindingUser("{{Auth::user()->id}}",data.client_id);
                break;
            case 'binding_success'://用户绑定(用于当前用户刷新页面时,对我方用户id进行重新绑定)
                console.log(data.msg + 'A');
                break;
            case 'content_success'://接受好友发来的用户消息
                content_success(data);
                break;
            case 'ping'://心跳检测
                ws.send(JSON.stringify({
                    'type':"pong"
                }));
                break;
            case 'files_success'://接收好友base64文件
                //console.log(data);
                restoreFile(data);
                break;
            default:
                console.log('绑定失败');
        }
    };

    ws.onclose = function()
    {
        // 关闭 websocket
        alert("连接已关闭...");
    };



    /**
     * 绑定我方用户id方法
     * @param user_id 我方用户id(数据来自“加载页面控制器”传递进来)
     * @param client_id GatewayWorker发现有页面发起连接时,将对应连接的client_id发给网站页面,注意:此id是唯一的,每次重新链接都会发送一个新的client_id给我们
     * 我方用户id与client_id的关系为一对多,及我方id为一个,可对应多个client_id。
     * 通信时已我方用户id作为唯一标识!
     */
    function bindingUser(user_id,client_id) {
        $.ajax({
            type : "POST", //提交方式
            url : "{{route('im.bindingUser')}}",//路径
            data : {
                '_token':'{{csrf_token()}}'//laravel 防止ajax POST请求报419错误方法
                ,'user_id' : user_id
                ,'client_id' : client_id
            },//数据,这里使用的是Json格式进行传输
            success : function(result) {//返回数据根据结果进行相应的处理
                var data = JSON.parse(result);//接受到服务器给我返回的JSON数据并进行解析
                if (data.success) {
                    // console.log('绑定结果:' + data.msg);
                } else {
                    alert('绑定失败22222');
                }
            }
        });
    }

    /**
     * 接收处理好友发来的数据
     * @param data
     */
    function  content_success(data) {
        console.log(data);
        alert(1111);return false;
        let class_name = '.chat_ul_' + data.addresser_id;//设定需要显示的class名称
        let demo = "<li class=\"his_content chat\">\<n></n>" +
            "           <span>"+ data.msg +"</span>\<n></n>" +
            "       </li>";
        $(class_name).append(demo);
    }

    /**
     * 将base64文件进行还原展示
     * @param data
     */
    function restoreFile(data){
        console.log(data);
        switch (data.file_type) {
            case 'mp3':
                let chat_id = 'left';//对方发送li classe名
                showSendFile(data.msg,data.file_type,data.file_id,data.audio_time,chat_id);
                break;
            case 'a':
                //自定义业务逻辑
                break;
            case 'b':
                //自定义业务逻辑
                break;
            case 'c':
                //自定义业务逻辑
                break;
            default:
                break
        }
    }

    /**
     * 发送文件到指定用户
     * @param base64_data base64格式的文件
     * @param type 指定的文件类型
     */
    function sendFile_user(base64_data,file_type){
        $.ajax({
            url:"{{route('im.sendFile_user')}}",
            type:"post",
            data: {
                'base64_data': base64_data,//base64文件
                'file_type': file_type,//文件类型
                '_token': '{{csrf_token()}}',//token过CSRF用的
                'recipients':"{{$addressee['id']}}",//收件人id
                'audio_time':audio_time,//录音时长(全局变量)
            },
            dataType:"json",
            success:function(data){
                if(data.success == true){
                    console.log(data);
                    alert("上传成功");
                    let audio_time_2 = data.audio_time;//录音时长
                    let file_id = data.file_id;//文件唯一id
                    let chat_id = 'right';//我方发送li classe名
                    showSendFile(base64_data,file_type,file_id,audio_time_2,chat_id);//显示发送的文件
                }else{
                    alert("上传失败");
                }
            },
            error:function(){
                console.log("上传失败");
            }
        });
    }
</script>

注意:1.首先我没把我写的js全拿出来,报错说方法找不到的,可以根据我的注释自己写业务逻辑,或者直接把方法名删掉都可以。
重点:这里有好朋友回报:ws或者wss链接超时、无法连接错误。这可能是你的服务器防火墙引起的,直接关闭防火墙简单粗暴,问题直接解决绝。(但是这个解决方案不推荐,请自行优化解决。)
如果你关闭了服务器防火墙依然无法解决,请你仔细阅读官方手册《GatewayWorker手册->-开发必读》章节的上半章内容中的6条注意事项,耐心排查。

总结

客户端(H5页面)、workerman服务端、php服务端 三者之间的关系

1.通俗易懂的讲法:我们把这其中的关系想象成‘邮差送信服务’
客户端=发件人/收件人。
workerman服务端 = 邮差,负责跑腿的。
php服务端 = 邮局,给邮差安排任务的地方。

发件人A想要发消息,他先去邮局告诉邮局发件人A的基本身份信息,在告诉邮局要邮寄的东西是什么,需要邮寄给谁。
邮局收到了发件人A的诉求。开始安排邮差去送信
邮差根据发件人A提供的信息去收件人的地址执行送信业务。

他们所扮演的角色就是这样。

返回上一篇《PHP+Laravel5.8+GatewayWorker实现即时文字聊天,文件互传功能(第1篇:开发前的准备)》

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值