聊天系统代码详解

  • 2017-08-30
  • 0
  • 0

服务端入口代码

include_once ‘server/WebSocket.php’;
$webSocket = new \WebIM\WebSocket();
$webSocket->run();

服务端主要代码

/**
 * Created by PhpStorm.
 * User: ShanyuLiang
 * Date: 2017/8/4
 * Time: 15:49
 */
namespace WebIM;

use Swoole\WebSocket\Server;

class WebSocket
{
    private $server;
    private $table;

    public function __construct()
    {
        $this->createTable();
    }

    /**
     * 启动
     */
    public function run()
    {
        $this->server = new Server('0.0.0.0', '9502');
        $this->server->set(
            array(
                'daemonize' => false,      // 是否是守护进程
                'max_request' => 100,    // 最大连接数量
                'worker_num' => 2,
                'dispatch_mode' => 2,
                'debug_mode'=> 1,
                // 心跳检测的设置,自动踢掉掉线的fd
                'heartbeat_check_interval' => 5,
                'heartbeat_idle_time' => 600,
            )
        );
        $this->server->on('open', [$this, 'open']);
        $this->server->on('message', [$this, 'message']);
        $this->server->on('close', [$this, 'close']);

        $this->server->start();
    }

    /**
     * @param Server $server
     * @param $request
     */
    public function open(Server $server, $request)
    {

    }

    private function allUser()
    {
//        $users = [];
//        foreach ($this->table as $row) {
//            $users[] = $row;
//        }
//        return $users;
    }

    /**
     * @param Server $server
     * @param $frame
     */
    public function message(Server $server, $frame)
    {
        $data = json_decode($frame->data,true);
        if(is_array($data) && !empty($data)){
            if(isset($data['type']) && $data['type'] == 1){
                $user = [
                    'fd'  => $frame->fd,
                    'uid' => $data['uid'],
                    'avatar' => $data['avatar'],
                    'username' => $data['username']
                ];
                $this->table->set($frame->fd, $user);
            }else{
                $this->pushMessage($server, $data, $frame->fd);
            }
        }
    }


    /**
     * @param Server $server
     * @param $fd
     */
    public function close(Server $server, $fd)
    {
//        $user = $this->table->get($fd);
        $this->table->del($fd);
        $this->server->close($fd);
    }

    /**
     * 遍历发送消息
     *
     * @param Server $server
     * @param $message
     * @param $messageType
     * @param int $skip
     */
    private function pushMessage(Server $server, $message, $frameFd)
    {
        if(!empty($message)){
//            $user = $this->table->get($frameFd);
            if($message['type'] == 'group'){
                $member = explode(',',$message['member']);
                foreach ($this->table as $row) {
                    if (in_array($row['uid'],$member) && $frameFd != $row['fd']) {
                        $server->push($row['fd'], json_encode([
                                'id' => $message['from'],
                                'username' => $message['username'],
                                'content' => $message['content'],
                                'avatar' => $message['avatar'],
                                'toId'  => $message['to'],
                                'type' =>  $message['type'],
                                'datetime' => time()*1000
                            ])
                        );
                    }
                }
            }else{
                foreach ($this->table as $row) {
                    if ($row['uid'] == $message['to']) {
                        $server->push($row['fd'], json_encode([
                                'id' => $message['from'],
                                'username' => $message['username'],
                                'content' => $message['content'],
                                'avatar' => $message['avatar'],
                                'toId'  => $message['to'],
                                'type' =>  $message['type'],
                                'datetime' => time()*1000
                            ])
                        );
                    }
                }
            }
        }
    }

    /**
     * 创建内存表
     *swoole_table一个基于共享内存和锁实现的超高性能,并发数据结构。用于解决多进程/多线程数据共享和同步加锁问题。
     */
    private function createTable()
    {
        $this->table = new \swoole_table(1024);
        $this->table->column('fd', \swoole_table::TYPE_INT);
        $this->table->column('uid', \swoole_table::TYPE_INT);
        $this->table->column('username', \swoole_table::TYPE_STRING, 255);
        $this->table->column('avatar', \swoole_table::TYPE_STRING, 255);
        $this->table->create();
    }
}

客户端代码

/**
 * Created by ShanyuLiang on 2017/8/10.
 */
layui.use('layim', function(layim){
    //链接服务端
    var ws = new WebSocket("ws://127.0.0.0:9502");
    //先来个客服模式压压精
    layim.config({
        init:{
            url: 'index/getInfo',
            data:{id:id}
        },
        members: {
            url: 'index/getMember',
        },
        //上传图片接口
        uploadImage: {
            url: '/index/upPic', //(返回的数据格式见下文)
            type: 'post' //默认post
        },

        //上传文件接口
        uploadFile: {
            url: '/upload/file', //(返回的数据格式见下文)
            type: 'post' //默认post
        },

        tool: [{
            alias: 'code',
            title: '代码',
            icon: ''
        }],
        brief: false, //是否简约模式(如果true则不显示主面板)
        initSkin: '1.jpg',
        notice: true,
        title: '开始聊天',
        //        skin: ['aaa.jpg']  //皮肤列表
    });

    //链接成功时触发
    ws.onopen = function(){
        var info = '{"type":1,"uid":'+id+',"username":"'+username+'","avatar":"'+avatar+'"}';
        ws.send(info);
    };

    //监听发送消息
    layim.on('sendMessage', function(data){
        var To = data.to;
        var from= data.mine;
        if(To.type === 'friend'){
            var msg = '{"from":'+from.id+',"content":"'+from.content+'","username":"'+from.username+'","avatar":"'+from.avatar+'"' +
                ',"to":'+To.id+',"type":"'+To.type+'"}';
            layim.setChatStatus('<span style="color:#FF5722;">对方正在输入。。。</span>');
        }else{
            var msg = '{"from":'+from.id+',"content":"'+from.content+'","username":"'+from.username+'","avatar":"'+from.avatar+'"' +
                ',"to":'+To.id+',"member":"'+To.member+'","type":"'+To.type+'"}';
        }
        ws.send(msg);
    });

    //接收消息
    ws.onmessage = function(res){
        var data = JSON.parse(res.data);
        console.log(data);
        if(data.type == 'group'){
            var to = data.toId;
        }else{
            var to = data.id;
        }
        obj = {
            username: data.username,
            avatar: data.avatar,
            id: to,
            type: data.type,
            content: data.content,
            mine: false,
            timestamp: data.datetime
        }
        layim.getMessage(obj);
    };
});

评论

还没有任何评论,你来说两句吧