layim和Gatewayworker组合的实时通讯

今天是第二次重新开发使用layim和Gatewayworker,但是由于第一次没有写文档,导致这一次就跟第一次一样,一头雾水,重新开始看文档研究,导致遇到一个瓶颈,怎么都过不去。所以,以这篇文章开始,以后所有的知识点,全部写上文档。

首先如果是快速入手的快,直接从http://www.workerman.net/windows下载,worker。然后解压放到项目中去。

,除了以上这三个文件,其他文件不需要做任何修改。

 

1 Events.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;
use \GatewayWorker\Lib\DbConnection;
/**
 * 主逻辑
 * 主要是处理 onConnect onMessage onClose 三个方法
 * onConnect 和 onClose 如果不需要可以不用实现并删除
 */
class Events
{
    public static $db;
    public static $uuid = [];
    public static $clientid = [];

    public static function onWorkerStart()
    {
        self::$db = new DbConnection('xxx', '3306', 'xxx', xxx', 'xxx');
    }

    /**
     * 当客户端连接时触发
     * 如果业务不需此回调可以删除onConnect
     * 
     * @param int $client_id 连接id
     */
    public static function onConnect($client_id){
//        Gateway::sendToClient($client_id, json_encode($noonline));
    }
    
   /**
    * 当客户端发来消息时触发
    * @param int $client_id 连接id
    * @param mixed $message 具体消息
    */
   public static function onMessage($client_id, $message)
   {

       $data = json_decode($message,true);
        switch($data['type']) {
            //当有用户上线
            case 'reg':
                //绑定uid 用于数据分发
                $uid = $data['data']['id'];
                Gateway::bindUid($client_id, $uid);
                self::$clientid[$client_id] = $uid;

                //如果数组中不存在键值uid,那么表示是第一次登陆,更新数据库
                if(!isset(self::$uuid[$uid])){
                    self::$uuid[$uid] = $uid;
                    self::$db->update('im_user_baseInfo')->cols(array('status'=>1))->where('id='.$uid)->query();
                }
                break;

            case 'chatMessage':
                //正常聊天

                $to_user = $data['data']['to']['id'];
                $from_user = $data['data']['mine']['id'];
                $time = time();
                $content = quotationMarks($data['data']['mine']['content']);

                $msg = array(
                    'username'=>    $data['data']['mine']['username'],//消息来源用户名
                    'avatar'=>     $data['data']['mine']['avatar'],
                    'id'=>         $from_user,//消息的来源ID(如果是私聊,则是用户id,如果是群聊,则是群组id)
                    'content'=>    $content,
                    'type'=>       'friend',//聊天窗口来源类型,从发送消息传递的to里面获取
                    'mine'=>       false,//是否我发送的消息,如果为true,则会显示在右方
                    'timestamp'=>  date('Y-m-d h:i:s',$time),
                    'emit'=>       'chatMessage'
                );
                //发送给自己的,同客户端同步
                $msg2 = array(
                    'username'=>    $data['data']['mine']['username'],//消息来源用户名
                    'avatar'=>     $data['data']['mine']['avatar'],
                    'id'=>         $to_user,//消息的来源ID(如果是私聊,则是用户id,如果是群聊,则是群组id)
                    'content'=>    $content,
                    'type'=>       'friend',//聊天窗口来源类型,从发送消息传递的to里面获取
                    'mine'=>       true,//是否我发送的消息,如果为true,则会显示在右方
                    'timestamp'=>  date('Y-m-d h:i:s',$time),
                    'emit'=>       'sendme'
                );
                $sql = array(
                    'from_user'=>$from_user,
                    'to_user'=>$to_user,
                    'type'=>1,//目前默认都是朋友
                    'content'=>$content,
                    'msg_type'=>1,//1:文本 2:资源(图片,文件等)
                    'add_time'=>$time,
                    'is_read'=>1,//已经查看
                );

                //判断是否在线
                if (Gateway::isUidOnline($to_user)) {
                    Gateway::sendToUid($to_user, json_encode($msg));
                    self::$db->insert('im_message')->cols($sql)->query();
                }
                else
                {
                    //如果对方离线,发送系统消息
                    $sql['is_read'] = 0;
                    self::$db->insert('im_message')->cols($sql)->query();

                    $noonline = array(
                        'emit'=>'status',
                        'fromid'=>-2,
                        'id'=>-2,
                        'status'=>0,
                    );
                    Gateway::sendToClient($client_id, json_encode($noonline));
                }

                //根据uid获取其他客户端的client_id
                $from_client_list = Gateway::getClientIdByUid($from_user);

                unset($from_client_list[array_search($client_id,$from_client_list)]);
                foreach ($from_client_list as $from_client){
                    Gateway::sendToClient($from_client, json_encode($msg2));
                }
                break;
            
            //查询是否在线的状态
            case 'status':
                $to_user = $data['data']['id'];
                $noonline = array(
                    'emit'=>'status',
                    'fromid'=>-2,
                    'id'=>-2,
                    'status'=>0
                );
                if (Gateway::isUidOnline($to_user)) {
                    $noonline['status'] = 1;
                }
                Gateway::sendToClient($client_id, json_encode($noonline));

                break;

            //修改聊天记录为已读状态
            case 'isread':
                $username = quotationMarks($data['data']['name']);
                $uid = quotationMarks($data['data']['mid']);
                $from_user = self::getUserinfoByname($username);

                //改变消息的已读状态
                if(!empty($from_user) && !empty($uid)) self::changeIsread($from_user,$uid,1);
                break;
        }
        
   }
   
   /**
    * 当用户断开连接时触发
    * @param int $client_id 连接id
    */
   public static function onClose($client_id)
   {
       $id = self::$clientid[$client_id];
       unset(self::$clientid[$client_id]);
       //如果长度等于0,说明绑定该uid的所有客户端都下线了
       if(count(Gateway::getClientIdByUid($id)) == 0){
           unset(self::$uuid[$id]);
           self::$db->update('im_user_baseInfo')->cols(array('status'=>0))->where('id='.$id)->query();
       }
//       var_export(self::$clientid);

   }


    /**
     * 查询该用户名对应的用户
     * @param $username
     * @return mixed
     */
    public static function getUserinfoByname($username){
        $result = self::$db->select('id')->from('im_user_baseInfo')->where("username= '$username' ")->column();
        return $result[0];
    }

    /**
     * Mobile将消息设置为已读状态
     * @param $from_user
     * @param $to_user
     * @param $is_read
     */
    public static function changeIsread($from_user,$to_user,$is_read){
        $sql = "UPDATE im_message SET is_read = $is_read WHERE from_user = $from_user AND to_user = $to_user";
        self::$db->query($sql);
    }



}
/**
 * 数据接收正则匹配,去掉字符串中的单引号和双引号
 * add by fpc  time:2017-03-29
 */
function quotationMarks($str){
    // 正则表达式匹配中文(UTF8编码)
    if(preg_match_all('/\'(.*?)\'/',$str)){
        $str = str_replace("\'",'',$str);
        if(preg_match_all('/\"(.*?)\"/',$str)){
            $str = str_replace('\"','',$str);
        }
        return trim($str);
    }else{
        return addslashes(trim($str));
    }
}
View Code

2start_businessworker.php

3start_gateway.php

4客户端

总共就以上这些代码,以上代码仅在windows下的代码,今天遇到一个问题,由于文件和方法是从linux移动过来的,所以调试的时候就出现了一下问题

服务器一直是可以的,但是使用

var socket = new WebSocket('ws://192.168.0.188:8484');打开的时候,就一直连接不上,原因就在于在start_gateway.phpz这个文件中,
$gateway = new Gateway("websocket://0.0.0.0:8484");这一句,linux是    tcp://..........  windows是websocket。
接下来就是无限发挥的时刻了

如果是https的服务器,那么使用
var socket = new WebSocket('wss://192.168.0.188:8484');




第二部分

摘要:在一个服务器上可以有多个 WebSocket部署

说明:第二个使用的是https

当我在同一个服务器上,使用workman部署第二个websocket的时候如图所示为了防止端口号冲突,要修改端口号与以第一个部署的服务器的端口号全部不一样

因为使用了https,与http的区别就是增加了这两层代码

在前台的js中

var socket = new WebSocket('wss://www.xxx.com:7272');  wss://域名+端口号,端口号要注意和gate的一致

转载于:https://www.cnblogs.com/fpcing/p/7873955.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值