使用Swoole服务搭建简易聊天室

前言:

之前写过一篇关于swoole的安装搭建的文章。也测试了搭建TCP协议的服务。但是今天我要介绍的是WebSocket协议,WebSoket协议的出现,解决了http协议的很大的一个缺陷。那就是服务器端无法直接向客户端或者说是浏览器端发送信息。而是要等待客户端的请求,才能发送数据给他。要想达到实时数据更新的话,就不得不使用轮询。但是轮询其实非常的损耗性能,解决起来也不够优雅。

WebSocket基类介绍

之前有介绍过如何搭建Swoole服务,其实swoole的类的继承,非常契合协议之间的关系。这里再次感叹大神就是大神,写的东西,简单易懂又透露出高级感。

首先要讲解下,通信协议的基础

通信协议

也就是说,WebSocke协议和http协议都是基于TCP的协议。也就是三次握手,来保证通信的成功和完整。
同样的在swoole里面,有一个基类就是server类,还有两个类分别是httpServer类和WebSoket类继承子server类。就和他们之间网络协议的关系一样的。

也就是说server类中的属性,方法,回调方法在webSocket类中都是被继承,可以使用的

搭建一个WebSocket服务

这次我写的这个服务,采用面向对象的形式来写,代码读起来会比较清晰。

  1. 我们创建一个聊天室类
class Chat
{
    const HOST = '0.0.0.0';//ip地址 0.0.0.0代表接受所有ip的访问
    const PART = 81;//端口号
    private $server = null;//单例存放websocket_server对象
}
  1. 根据手册了解到,我们需要调用websocket对象上的on方法来监听事件,并且书写回调函数。我们将这一部分代码写到构造函数中去,也就是在实例化对象的时候,就开启服务
    public function __construct()
    {
        //实例化swoole_websocket_server并存储在我们Chat类中的属性上,达到单例的设计
        $this->server = new swoole_websocket_server(self::HOST, self::PART);
        //监听连接事件
        $this->server->on('open', [$this, 'onOpen']);
        //监听接收消息事件
        $this->server->on('message', [$this, 'onMessage']);
        //监听关闭事件
        $this->server->on('close', [$this, 'onClose']);
        //设置允许访问静态文件
        $this->server->set([
            'document_root' => '/grx/swoole/public',//这里传入静态文件的目录
            'enable_static_handler' => true//允许访问静态文件
        ]);
        //开启服务
        $this->server->start();
    }
  1. 刚才说了,这里不光要监听事件,还要编写回调方法。让事件被触发的时候,调用这个方法
 /**
     * 连接成功回调函数
     * @param $server
     * @param $request
     */
    public function onOpen($server, $request)
    {
        echo $request->fd . '连接了' . PHP_EOL;//打印到我们终端
    }

    /**
     * 接收到信息的回调函数
     * @param $server
     * @param $frame
     */
    public function onMessage($server, $frame)
    {
        echo $frame->fd . '来了,说:' . $frame->data . PHP_EOL;//打印到我们终端
        foreach ($server->connections as $fd) {//遍历TCP连接迭代器,拿到每个在线的客户端id
            //将客户端发来的消息,推送给所有用户,也可以叫广播给所有在线客户端
            $server->push($fd, json_encode(['no' => $frame->fd, 'msg' => $frame->data]));
        }
    }

    /**
     * 断开连接回调函数
     * @param $server
     * @param $fd
     */
    public function onClose($server, $fd)
    {
        echo $fd . '走了' . PHP_EOL;//打印到我们终端
    }
  1. 当还有最后的一步,就是实例化我们聊天室类
$obj = new Chat();

经过思_2c04的提醒。之前使用一个类的成员变量的方式来储存客户端的句柄是错误且低效的。swoole为我们提供了很好的TCP连接迭代器,专门用于广播等场景。之前的代码块里已经修正。以下是swoole源码中对TCP的注释。还举例说明了用法。亲测可用。

    /**
     * TCP连接迭代器,可以使用foreach遍历服务器当前所有的连接,此属性的功能与swoole_server->connnection_list是一致的,但是更加友好。遍历的元素为单个连接的fd
     *
     * 连接迭代器依赖pcre库,未安装pcre库无法使用此功能
     *
     *      foreach($server->connections as $fd)
     *      {
     *          $server->send($fd, "hello");
     *      }
     *
     *      echo "当前服务器共有 ".count($server->connections). " 个连接\n";
     *
     * @var \Swoole\Connection\Iterator
     */
    public $connections;

那么我先简单介绍下流程,因为里面很多方法的使用,在官网的手册中已经写的很详细了所以这里就不做过多的解释了。只描述下流程

流程图.png

这里最关键的一步就是,将消息发给每个在线的客户端。聊天室的关键其实就是,让自己的发言,能让别人看到,别的人发言,我也能看到。所以,我们需要websocket这样的服务器主动发送消息给客户端才可以办到

客户端部分

由于博主本身是搞php后端的,前端只是略懂,加之在公司都是前后端分离,很久没写前端代码了。大家看看就好,我就不过多介绍了

<!doctype html>

<html>

<head>

    <meta charset="utf-8">

    <title>色情聊天室</title>

    <script src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script>

</head>

<body>

<textarea class="log" style="width: 100%; height: 500px;">

=======色情聊天室======

</textarea>

<input type="button" value="连接" onClick="link()">

<input type="button" value="断开" onClick="dis()">

<input type="text" id="text">

<input type="button" value="发送" onClick="send()">

<script>

    function link(){

        var url='ws://gongruixiang.club:81';

        socket=new WebSocket(url);

        socket.onopen=function(){log1('连接成功')}

        socket.onmessage=function(msg){log(msg.data);console.log(msg);}

        socket.onclose=function(){log1('断开连接')}

    }

    function dis(){

        socket.close();

        socket=null;

    }

    function log1(var1) {
        $('.log').append(var1+'\r\n');
    }
    function log(var1){
      var  v=$.parseJSON(var1)
        $('.log').append('用户'+v['no']+'说:'+v['msg']+'\r\n');
    }

    function send(){
        var text=$('#text').val();

        socket.send(text);
    }

    function send2(){

        var json = JSON.stringify({'type':'php','msg':$('#text2').attr('value')})

        socket.send(json);

    }

</script>

</body>

</html>
前端效果

服务器终端效果

好了,今天就先写到这里,如果有不对的地方希望获得指点。关于swoole的文章我会持续更新。谢谢

以上

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272

推荐阅读更多精彩内容

  • 原文地址:http://www.ibm.com/developerworks/cn/java/j-lo-WebSo...
    敢梦敢当阅读 8,807评论 0 50
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    X先生_未知数的X阅读 15,937评论 3 118
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,103评论 18 139
  • 15年的冬天,我高三,住校生,一礼拜回一次家,冬天天黑的特别早,周练完走出校门满身疲惫,家离学校特别远,要转好几趟...
    栗格格阅读 170评论 0 3
  • 《华严经》:经中之王 大乘佛教有三部公认的“经王”,分别是《华严经》、《法华经》和《楞严经》。其中最被推崇备至的,...
    西安华严寺阅读 678评论 0 0