easyswoole实现在线聊天室功能

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: easyswoole实现在线聊天室功能

一 : 安装easyswoole,可参考http://www.php20.cn/article/82


把example/example\multiUsage_01\的实例覆盖到src,访问ip:端口(9501)/test/websocket.php可查看最简单实例


灵活组合加上前端可以做的非常好


image.png


以下为我自己项目修改后的代码,看不懂可以去看简单实例


前台js


varuser_info;

varis_connect = 0;

varwebsocket;

varmsg = 0;

is_login();

autoWidth();

varinitWebSocket = function() {

    varwsServer = 'ws://139.199.164.211:9501';

    websocket = newWebSocket(wsServer);

    websocket.onopen = function(evt) {

        varhtml = '<p>正在连接服务器...</p>';

        addLine(html);

    };

    websocket.onclose = function(evt) {

        varhtml = '<p>服务器异常关闭,正在重连</p>';

        addLine(html);

        socket_connect();

    };

    websocket.onmessage = function(evt) {

        vardata = JSON.parse(evt.data);

        if(data['status'] == false) {

            msgTip(data['info']);

            return;

        }

        if(parseInt(data['fd']) > 0) {

            $.ajax({

                url: SiteUrl + 'index.php?g=Res&m=Chat&a=add_client',

                dataType: 'JSON',

                data: {fd: data['fd'], key: key},

                type: 'POST',

                success: function(res) {

                    check_login(res);

                    /*  if (res['status'] == false) {

                     msgTip(res['info']);

                     return;

                     }*/

                    is_connect = 1;

                    user_info = res['data'];

                    varhtml = '<p>连接服务器成功</p>';

                    addLine(html);

                }

            });

        else{

            if(data['user_info']['id'] == user_info['id']) {

                addMyLine(data['msg']);

            else{

                addOthLine(data['msg'],data['user_info']);

            }

        }

 

        if(msg == 0) {//消息为0则返回最近聊天记录的10条

            get_msg();

        }

        msg++;

        if(msg >= 50) {

            $('#speak_box').find('div').eq(-30).prevAll().remove();

            msg = 30;

        }

    };

    websocket.onerror = function(evt, e) {

        loadingShow(evt.data);

    };

};

 

initWebSocket();

 

varsocket_connect = function() {

    window.connect = setInterval(function() {

        initWebSocket();

        if(is_connect == 1) {

            clearInterval(window.connect);

        }

    }, 5000);

};

 

functionaddLine(data) {

    varhtml = '<div class="answer">';

    html += data;

    html += '</div>';

    $('#speak_box').append(html);

}

functionaddMyLine(data) {

    varhtml = '<div class="question">';

    html += '<div class="heard_img right"><img src="'+ Host + '/data/upload/avatar/'+ user_info.avatar + '"></div>';

    html += '<div class="question_text clear" style="max-width: 285px;"><p>'+ html2Escape(data) + '</p><i></i></div>';

    html += '</div>';

    $('#speak_box').append(html);

}

functionaddOthLine(msg,user) {

    if(user.avatar == null) {

        user.avatar = 'admin.gif';

    }

    varhtml = '<div class="answer">';

    html += '<div class="heard_img left"><p>'+ user.user_nicename + '</p><img src="'+ Host + '/data/upload/avatar/'+ user.avatar + '"></div>';

    html += '<div class="answer_text" style="max-width: 285px;"><p>'+ html2Escape(msg) + '</p><i></i></div>';

    html += '</div>';

    $('#speak_box').append(html);

}

 

functionsend(msg, to_user_id) {

    to_user_id = to_user_id ? to_user_id : 0;

 

    $.ajax({

        url: SiteUrl + 'index.php?g=Res&m=Chat&a=add_msg',

        dataType: 'JSON',

        data: {key: key, to_user_id: to_user_id, msg: msg},

        type: 'POST',

        success: function(res) {

            check_login(res);

            if(res['status'] == false) {

                msgTip(res['info']);

                return;

            }

            data = '{"msg":"'+ msg + '","key":"'+ key + '"}',

                websocket.send(data);

        }

    });

}

 

functionget_msg() {

    $.ajax({

        url: SiteUrl + 'index.php?g=Res&m=Chat&a=get_msg',

        dataType: 'JSON',

        data: {key: key},

        type: 'POST',

        success: function(res) {

            check_login(res);

            if(res['status'] == false) {

                msgTip(res['info']);

                return;

            }

            for(varinres['data']['list']){

                varvo = res['data']['list'][x];

                if(vo['user_id'] == user_info['id']) {

                    addMyLine(vo['content']);

                else{

                    addOthLine(vo['content'],vo);

                }

            };

        }

    });

}

 

 

varwen = document.getElementById('wenwen');

function_touch_start(event) {

    event.preventDefault();

    $('.wenwen_text').css('background''#c1c1c1');

    $('.wenwen_text span').css('color''#fff');

    $('.saying').show();

}

 

function_touch_end(event) {

    event.preventDefault();

    $('.wenwen_text').css('background''#fff');

    $('.wenwen_text .circle-button').css('color''#666');

    $('.saying').hide();

    varstr = '<div class="question">';

    str += '<div class="heard_img right"><img src="../assets/images/chat/dglvyou.jpg"/></div>';

    str += '<div class="question_text clear"><p>不好意思,我听不清!</p><i></i>';

    str += '</div></div>';

    $('.speak_box').append(str);

    for_bottom();

    setTimeout(function() {

        varans = '<div class="answer"><div class="heard_img left"><img src="../assets/images/chat/dglvyou.jpg"/></div>';

        ans += '<div class="answer_text"><p>我不知道你在说什么?</p><i></i>';

        ans += '</div></div>';

        $('.speak_box').append(ans);

        for_bottom();

    }, 1000);

}

 

wen.addEventListener("touchstart", _touch_start, false);

wen.addEventListener("touchend", _touch_end, false);

 

functionfor_bottom() {

    varspeak_height = $('.speak_box').height();

    $('.speak_box,.speak_window').animate({scrollTop: speak_height}, 500);

}

 

functionautoWidth() {

    $('.question_text').css('max-width', $('.question').width() - 60);

}

 

functionto_write() {

    $('.wenwen_btn img').attr('src''../assets/images/chat/yy_btn.png');

    $('.wenwen_btn').attr('onclick''to_say()');

    $('.write_box,.wenwen_help button').show();

    $('.circle-button,.wenwen_help a').hide();

    $('.write_box input').focus();

    for_bottom();

}

 

functionto_say() {

    msgTip('暂不支持语音聊天');

    return;

    $('.write_list').remove();

    $('.wenwen_btn img').attr('src''../assets/images/chat/jp_btn.png');

    $('.wenwen_btn').attr('onclick''to_write()');

    $('.write_box,.wenwen_help button').hide();

    $('.circle-button,.wenwen_help a').show();

}

 

 

functionkeyup() {

    varfooter_height = $('.wenwen-footer').outerHeight(),

        text = html2Escape($('.write_box input').val()),

        str = '<div class="write_list">'+ html2Escape(text) + '</div>';

    if(text == ''|| text == undefined) {

        $('.write_list').remove();

    else{

        $('.write_list').remove();

        $('.wenwen-footer').append(str);

        $('.write_list').css('bottom', footer_height);

    }

}

 

functionup_say() {

    $('.write_list').remove();

    vartext = $('.write_box input').val();

    if(text.length < 1) {

        msgTip('内容不能为空');

        return;

    }

    $('.write_box input').val('');

    $('.write_box input').focus();

    autoWidth();

    for_bottom();

    send(text);

    /*

     setTimeout(function () {

     var ans = '<div class="answer"><div class="heard_img left"><img src="../assets/images/dglvyou.jpg"/></div>';

     ans += '<div class="answer_text"><p>您发送的文字是:' + text + '</p><i></i>';

     ans += '</div></div>';

     $('.speak_box').append(ans);

     for_bottom();

     }, 1000);*/

}

 

functionremoveHtmlTab(tab) {

    returntab.replace(/<[^<>]+?>/g, '');//删除所有HTML标签

}

 

functionhtml2Escape(sHtml) {

    returnsHtml.replace(/[<>&"]/g, function (c) {

        return {'<': '&lt;', '>': '&gt;', '&': '&amp;', '"': '&quot;'}[c];

    });

}


后台event.php监听文件

<?php

/**

 * Created by PhpStorm.

 * User: yf

 * Date: 2017/1/23

 * Time: 上午12:06

 */

 

namespaceConf;

 

 

useApp\Model\Chat\Chat;

useCore\AbstractInterface\AbstractEvent;

useCore\AutoLoader;

useCore\Component\Di;

useCore\Component\Logger;

useCore\Component\Version\Control;

useCore\Http\Request;

useCore\Http\Response;

useCore\Swoole\SwooleHttpServer;

useCore\Swoole\Timer;

useApp\Utility\Mysql;

 

classEvent extendsAbstractEvent

{

    functionframeInitialize()

    {

        // TODO: Implement frameInitialize() method.

        date_default_timezone_set('Asia/Shanghai');

        $loader= AutoLoader::getInstance();

        $loader->requireFile("App/Vendor/MysqliDb/MysqliDb.php");

        $loader->requireFile("App/Vendor/Smarty/Smarty.class.php");

    }

 

    functionbeforeWorkerStart(\swoole_http_server $server)

    {

        // TODO: Implement beforeWorkerStart() method.

        //udp 请勿用receive事件

        //添加自带多协议监听

        $udp$server->addlistener("0.0.0.0", 9502, SWOOLE_SOCK_UDP);

        $udp->on('packet'function(\swoole_server $server$data$addr) {

            Logger::console("receive data {$data}");

            $server->sendto($addr['address'], $addr['port'], "Swoole: $data");

        });

 

//        $listener = $server->addlistener("0.0.0.0",9502,SWOOLE_TCP);

//        //混合监听tcp时    要重新设置包解析规则  才不会被HTTP覆盖,且端口不能与HTTP SERVER一致 HTTP本身就是TCP

//        $listener->set(array(

//            "open_eof_check"=>false,

//            "package_max_length"=>2048,

//        ));

//        $listener->on("connect",function(\swoole_server $server,$fd){

//            Logger::console("client connect");

//        });

//        $listener->on("receive",function(\swoole_server $server,$fd,$from_id,$data){

//            Logger::console("received connect");

//            $server->send($fd,"swoole ".$data);

//            $server->close($fd);

//        });

//        $listener->on("close",function (\swoole_server $server,$fd){

//            Logger::console("client close");

//        });

        $server->on("handshake"function(\swoole_http_request $request, \swoole_http_response $response) {

            Logger::console("handshake");

            //自定定握手规则,没有设置则用系统内置的(只支持version:13的)

            if(!isset($request->header['sec-websocket-key'])) {

                //'Bad protocol implementation: it is not RFC6455.'

                $response->end();

                returnfalse;

            }

            if(0 === preg_match('#^[+/0-9A-Za-z]{21}[AQgw]==$#'$request->header['sec-websocket-key'])

                || 16 !== strlen(base64_decode($request->header['sec-websocket-key']))

            ) {

                //Header Sec-WebSocket-Key is illegal;

                $response->end();

                returnfalse;

            }

 

            $keybase64_encode(sha1($request->header['sec-websocket-key']

                '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',

                true));

            $headersarray(

                'Upgrade'=> 'websocket',

                'Connection'=> 'Upgrade',

                'Sec-WebSocket-Accept'=> $key,

                'Sec-WebSocket-Version'=> '13',

                'KeepAlive'=> 'off',

            );

            foreach($headersas$key=> $val) {

                $response->header($key$val);

            }

            $response->status(101);

            $response->end();

            $result['status'] = true;

            $result['fd'] = $request->fd;

            SwooleHttpServer::getInstance()->getServer()->push($request->fd, json_encode($result));

        });

 

        //添加websocket回调事件

        $server->on("message"function(\swoole_websocket_server $server, \swoole_websocket_frame $frame) {

            Logger::console("接收数据:"$frame->data);

            $data= json_decode($frame->data, 1);

            $chat_modelnewChat();

            //验证用户

            $user_info$chat_model->get_info('select id,

    user_login,

    user_nicename,

    user_email,

    avatar,

    coin,

    mobile,

    money,

    freeze_money,

    sex

     from dm_users WHERE login_key="' . $data['key'] . '"limit 1');

     //这段的sql代码参考\example\multiUsage_01\App\Model\Goods\goods.php 的Mysql基类 方法

            if(!$user_info) {

                $resultarray();

                $result['status'] = false;

                $result['info'] = '你没有登陆账号!';

                $server->push($frame->fd, json_encode($result));

            else{

                if(empty($user_info['avatar'])){

                    $user_info['avatar']='admin.gif';

                }

                $data['user_info'] = $user_info;

                unset($data['key']);

                $data['status']=true;

                $data['msg'] = htmlentities($data['msg']);

                foreach($server->connections as$key=> $value) {

                    $server->push($value, json_encode($data));

                }

            }

        });

 

        $server->on("close"function(\swoole_http_server $server$fd) {

            $info= SwooleHttpServer::getInstance()->getServer()->connection_info($fd);

            if($info['websocket_status']) {

                Logger::console("websocket 客户端 {$fd} 关闭");

            }

        });

        //添加websocket回调事件结束

 

 

    }

 

    functiononStart(\swoole_http_server $server)

    {

        // TODO: Implement onStart() method.

        //使用event loop实现自定义 socket监听

        $listener= stream_socket_server(

            "udp://0.0.0.0:9503",

            $error,

            $errMsg,

            STREAM_SERVER_BIND

        );

        if($errMsg) {

            thrownew\Exception("listen fail");

        else{

            //加入event loop

            swoole_event_add($listenerfunction($listener) {

                $data= stream_socket_recvfrom($listener, 9503, 0, $client);

                Logger::console("rec data {$data} in event loop");

                stream_socket_sendto($listener"hello this is event loop", 0, $client);

            });

        }

    }

 

    functiononShutdown(\swoole_http_server $server)

    {

        // TODO: Implement onShutdown() method.

    }

 

    functiononWorkerStart(\swoole_server $server$workerId)

    {

        // TODO: Implement onWorkerStart() method.

        //为第一个worker添加一个定时器

        /*   if ($workerId == 0) {

               //10秒

               Timer::loop(10 * 1000, function () {

                   Logger::console("this is timer");

               });

           }*/

 

    }

 

    functiononWorkerStop(\swoole_server $server$workerId)

    {

        // TODO: Implement onWorkerStop() method.

    }

 

    functiononRequest(Request $request, Response $response)

    {

        // TODO: Implement onRequest() method.

    }

 

    functiononDispatcher(Request $request, Response $response$targetControllerClass$targetAction)

    {

        // TODO: Implement onDispatcher() method.

    }

 

    functiononResponse(Request $request, Response $response)

    {

        // TODO: Implement afterResponse() method.

    }

 

    functiononTask(\swoole_http_server $server$taskId$fromId$taskObj)

    {

        // TODO: Implement onTask() method.

    }

 

    functiononFinish(\swoole_http_server $server$taskId$fromId$taskObj)

    {

        // TODO: Implement onFinish() method.

    }

 

    functiononWorkerError(\swoole_http_server $server$worker_id$worker_pid$exit_code)

    {

        // TODO: Implement onWorkerError() method.

    }

}

注意:easyswoole只能在php-cli状态下运行,你修改完代码需要重启服务才能使代码生效,详细操作方法请看server.php


注意:该文章写的example文件夹已经转移到官网的实例文档中,源码已经删除

关于数据库操作的文件也已经移除,需要自己去实现model层的操作,可以查找相关的操作类


相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
7月前
|
前端开发 JavaScript 机器人
从头搭建一个在线聊天室(一)
从头搭建一个在线聊天室(一)
|
网络协议 计算机视觉
项目实战:Qt多人聊天室程序(在线、离线、离线信息再次登录后发送等)
项目实战:Qt多人聊天室程序(在线、离线、离线信息再次登录后发送等)
|
7月前
|
网络协议 小程序 数据库
轻松学会Python网络编程,搭建属于自己的聊天室
轻松学会Python网络编程,搭建属于自己的聊天室
|
7月前
|
前端开发 JavaScript NoSQL
在线聊天室优化之私聊
在线聊天室优化之私聊
在线聊天室优化之私聊
|
7月前
|
存储 NoSQL 前端开发
从头搭建一个在线聊天室(二)
从头搭建一个在线聊天室(二)
122 0
|
7月前
|
JSON NoSQL 前端开发
从头搭建一个在线聊天室(四)
从头搭建一个在线聊天室(四)
|
7月前
|
存储 前端开发 数据库
从头搭建一个在线聊天室(三)
从头搭建一个在线聊天室(三)
|
Web App开发 前端开发
|
移动开发 网络协议 前端开发
为美多商城(Django2.0.4)添加基于websocket的实时通信,主动推送,聊天室及客服系统
websocket是个啥? webSocket是一种在单个TCP连接上进行全双工通信的协议 webSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输
为美多商城(Django2.0.4)添加基于websocket的实时通信,主动推送,聊天室及客服系统
|
存储 JSON 网络协议
关于easyswoole实现websocket聊天室的步骤解析
关于easyswoole实现websocket聊天室的步骤解析
517 0