thinkphp 配合 GatewayWorker 制作网页聊天室(ssl)

1566
|
2019-10-26 11:48:43

官方文档:http://doc2.workerman.net/work-with-other-frameworks.html


借用官方的图解释大致思路

gatewayWorker 只负责推送消息,浏览器向服务器发送消息采用ajax方式,在控制器中处理消息逻辑然后调用gatewayWorker 发送消息

我这里使用的是tp5框架,centos7.2

1.下载gatewayWorker(不需要放到tp5项目中,它作为一个单独的服务)

地址:http://www.workerman.net/download/GatewayWorker.zip

2.进入gatewayWorker 目录,以守护进程开启服务

php start.php start -d

3.将服务添加到开机自启

vim /etc/rc.d/rc.local

在最后一行加入

php /home/www/GatewayWorker/start.php start -d

赋予执行权限

chmod +x /etc/rc.d/rc.local

4.下载GatewayClient,解压放到tp5 extend 目录

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

代码片段

js:

ws = new WebSocket("ws://你的服务器ip:8282");
            //接受到消息时
            ws.onmessage = function(e){
                //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绑定,group_id 群聊id自己生成,client_id是GatewayClient生成的,直接用即可
                        $.post('/index/data/in_chat', {client_id: data.client_id,group_id:group_id}, function(data){}, 'json');
                        break;
                    // 当mvc框架调用GatewayClient发消息时直接alert出来
                    case 'ping':
                        //心跳检测,不用做处理
                        break;
                    default :
                        //接收消息处理...

                }
            }

//发送消息
function send_message() {
        var message = $('.group-chat input[name="message"]').val();
        if(message.length > 88) {
            layer.msg('超出字符限制(88)');
            return false;
        }
        if(message.length < 3){
            layer.msg('发言长度不小于3');
            return false;
        }
        $.post('/index/chat/send_message',{group:group_id,message:message},function (res) {
            $(".message-input input").val('');
            //...
        })

    }

2.php代码片段

use GatewayClient\Gateway;
 //uid绑定
 public function in_chat(){
        Gateway::$registerAddress = '服务器ip:1238';
        $user = $this->user;//自行根据自己的业务逻辑获取用户信息
        $uid = $user['uid'];
        $client_id = input('post.client_id');
        $group_id = input('post.group_id');
        // client_id与uid绑定
        Gateway::bindUid($client_id, $uid);
        // 加入某个群组(可调用多次加入多个群组)
        Gateway::joinGroup($client_id, $group_id);
        //可以向群聊发送 ***已加入群聊
        Gateway::sendToGroup($group_id,'message');
    }
 //接收消息并使用gateWay发送
 public function send_message()
    {
        
        $user = $this->user;
        if(!$user)
            return ['code'=>300,'msg'=>'您还未登录'];
        Gateway::$registerAddress = '服务器ip:1238';
        $group = input('post.group');
        $message = input('post.message');
        $time = time();
        //消息记录保存到数据库
        
        $data = ['nick' => $user['nick'], 'photo' => $user['photo'], 'msg' => $message, 'time' => date('m-d H:i', $time),'uid'=>$user['uid']];
        // 向发送数据
        Gateway::sendToGroup($group, json_encode($data));
        return ['code'=>200];
    }

注意:以上端口一定要开放哦(防火墙,云服务器安全组) 8282,1238

GatewayWorker 配置

心跳检测配置 /home/www/GatewayWorker/Applications/YourApp/start_gateway.php

//心跳间隔
$gateway->pingInterval = 5;
 //心跳数据
$gateway->pingData = '{"type":"ping"}';

/home/www/GatewayWorker/Applications/YourApp/Event.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)
    {
        Gateway::sendToClient($client_id, json_encode(array(
            'type'      => 'init',
            'client_id' => $client_id
        )));
    }
    
   /**
    * 当客户端发来消息时触发
    * @param int $client_id 连接id
    * @param mixed $message 具体消息
    */
   public static function onMessage($client_id, $message)
   {
        // 向所有人发送
       // Gateway::sendToAll("$client_id said $message\r\n");
   }

//   /**
//    * 当用户断开连接时触发
//    * @param int $client_id 连接id
//    */
//   public static function onClose($client_id)
//   {
//       // 向所有人发送
//       GateWay::sendToAll("$client_id logout\r\n");
//   }
}

以上可能不够详细,可自行参考官方手册


10-30日更新

今天在项目应用到 https站点是socket连接失败 报错

failed: Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR

查找之后发现https站点连接的socket必须为wss的

下面为官方手册代码示例

http://doc2.workerman.net/secure-websocket-server.html

文件位置为 ./GatewayWorker/Applications/YourApp/start_gateway.php 

// 证书最好是申请的证书
$context = array(
    // 更多ssl选项请参考手册 http://php.net/manual/zh/context.ssl.php
    'ssl' => array(
        // 请使用绝对路径
        'local_cert'                 => '磁盘路径/server.pem', // 也可以是crt文件
        'local_pk'                   => '磁盘路径/server.key',
        'verify_peer'               => false,
        // 'allow_self_signed' => true, //如果是自签名证书需要开启此选项
    )
);
// websocket协议(端口任意,只要没有被其它程序占用就行)
$gateway = new Gateway("websocket://0.0.0.0:8282", $context);
// 开启SSL,websocket+SSL 即wss
$gateway->transport = 'ssl';

修改完成之后需要重启gateway服务

js 中把 

ws://ip:8282 修改为 
wss://domian:8282
w
we码sadasweq段 小部件
代码段 小部件