首页 > 编程语言 >PHP用Swoole的WebSocket功能编写聊天室Demo

PHP用Swoole的WebSocket功能编写聊天室Demo

时间:2023-06-24 17:36:24浏览次数:66  
标签:function WebSocket Swoole Demo ws msg return data

前提:

  1. linux环境下PHP有可用的Swoole扩展。
  2. 9501端口可访问。

后端

<?php
class Helper {
    /**
     * @function 将数组中的null值转化为空字符串
     * @param    $arr array 要转化的数组
     * @return   array
     * @other    void
     */
    public static function nullToEmptyString($arr) {
        if (! $arr) {
            return $arr;
        }

        foreach ($arr as $key => $value) {
            if (null === $value) {
                $arr[$key] = '';
            }
            if (is_array($value)) {
                $arr[$key] = static::nullToEmptyString($value);
            }
        }

        return $arr;
    }


    /**
     * @function 统一的RestFul风格的Api格式
     * @param    $code int    状态码
     * @param    $msg  string 显示的信息
     * @param    $data mixed  返回的数据
     * @return   string
     * @other    void
     */
    public static function jsonReturn($code = 0, $msg = '', $data = []) {
        header('Content-type:text/json;Charset=UTF-8');
        return json_encode([
            'code' => $code,
            'msg'  => $msg,
            'data' => $data === null ? [] : static::nullToEmptyString($data),
        ], JSON_UNESCAPED_UNICODE);
    }


    /**@function 配置人数
     * @param    $num
     * @return   bool
     */
    public static function setPersonNumber($num) {
        return file_put_contents(__DIR__ . '/personNum.txt', $num);
    }


    /**
     * @function 获取人数
     * @return   int
     */
    public static function getPersonNumber() {
        $file = __DIR__ . '/personNum.txt';
        if(! file_exists($file)) {
            return 0;
        }

        return file_get_contents($file);
    }


    /**
     * @function 发消息对外广播
     * @param    $ws  object \Swoole\WebSocket\Server
     * @param    $msg string 广播数据
     * @return   null
     */
    public static function broadcast(Swoole\WebSocket\Server $ws, $msg) {
        $fd = static::getPersonNumber();
        if($fd > 0) {
            for($i = 1; $i <= $fd; $i++) {
                $ws->push($i, $msg);
            }
        }

        return null;
    }
}


//创建WebSocket Server对象,监听0.0.0.0:9501端口。
$ws = new Swoole\WebSocket\Server('0.0.0.0', 9501);


//监听WebSocket连接打开事件。
$ws->on('Open', function ($ws, $request) {
    $ws->nickname = '游客'. $request->fd;
    Helper::setPersonNumber($request->fd);
    Helper::broadcast($ws, Helper::jsonReturn(0, '', ['type' => 'enter', 'user' => $ws->nickname, 'content' => '']));
    return null;
});


//监听WebSocket消息事件。
$ws->on('Message', function ($ws, $frame) {
    Helper::broadcast($ws, Helper::jsonReturn(0, '', ['type' => 'say', 'user' => $ws->nickname, 'content' => htmlspecialchars($frame->data)]));
    return null;
});


//监听WebSocket连接关闭事件。
$ws->on('Close', function ($ws, $fd) {
    Helper::setPersonNumber(-- $fd);
    Helper::broadcast($ws, Helper::jsonReturn(0, '', ['type' => 'leave', 'user' => $ws->nickname, 'content' => '']));
    return null;
});


$ws->start();

前端

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>简易聊天室</title>
    <style>
        body * {font-size: 20px;width: 400px;height: 40px;}
    </style>
</head>
<body>
    <input type="text" id="text">
    <input type="button" id="send" value="发送">
    <div id="box"></div>

</body>
<script>
    //初始化
    var websocket = new WebSocket('ws://192.168.3.180:9501/swoole.php');


    //打开事件
    websocket.onopen = function (evt) {
        document.getElementById('send').onclick = function() {
            var msg = document.getElementById('text').value;
            if(msg) {
                websocket.send(msg);
            }
        }
    };


    //消息事件
    websocket.onmessage = function (evt) {
        var data = JSON.parse(evt.data);
        var data = data.data;
        if(data.type == 'enter') {
            var e = '<p style="color:green">' + data.user + '进入聊天室</p>';
        } else if(data.type == 'leave') {
            var e = '<p style="color:red">' + data.user + '离开聊天室</p>';
        } else if (data.type == 'say') {
            var e = '<p style="color:black">' + data.user + '说:' + data.content + '</p>';
        }

        var element = document.getElementById('box').innerHTML += e;
    };


    //关闭事件
    websocket.onclose = function (evt) {
        console.log("WebSocket 已断开连接");
    };


    //错误事件
    websocket.onerror = function (evt, e) {
        console.log("WebSocket 错误:" + evt.data);
    };
</script>
</html>

标签:function,WebSocket,Swoole,Demo,ws,msg,return,data
From: https://www.cnblogs.com/phpphp/p/17501368.html

相关文章

  • springboot使用Websocket写一个聊天室
     1<!--websocket依赖-->2<dependency>3<groupId>org.springframework.boot</groupId>4<artifactId>spring-boot-starter-websocket</artifactId>5</dependency>目录 ......
  • 单例模式_demo
    参考:(15条消息)单例模式Demo_zixing08的博客-CSDN博客单例模式详细解析-知乎(zhihu.com)Singleton.java1packagecom.hmb;23publicclassSingleton{4privatestaticclassMySingleton{5privatestaticSingletonsingleton=newSingleton......
  • p61Demo8 DATA2 SEGMENT
    .386STACKSEGMENTUSE32DB200DUP(0)STACKENDSDATA1SEGMENTUSE16T1DW-50HT2DDFDATA1ENDS;DATA2SEGMENTUSE16BUFDB'ABCDEF'FDW70HDATA2ENDS;CODESEGMENTUSE16ASSUMECS:CODE,DS:DATA1,......
  • P52Demo3.1
    .386STACKSEGMENTUSE32DB200DUP(0)STACKENDSDATASEGMENTUSE16NUMDB11H,22H,33H,44HNENDDB0LENEQUNEND-NUM;不能直接用LENEQULEN-NUM,会导致宏嵌套太深DATAENDSCODESEGMENTUSE16ASSUMECS:CODE,DS:DATA,SS:STACKSTART......
  • Uniapp仿ChatGPT Stream流式输出(非Websocket)
    前言最近写一个chagpt小程序,流式输出可以使用websocket也可以使用stream来实现,这里就不折腾websocket的了,我发现uniapp实现流式输出的方式挺多的,主要是有些小程序还不兼容,花了点时间研究了一下。EventSourceEventSource也称为SSE(Server-SentEvents),是服务器推送的一个网络事件......
  • 安卓系列之 kotlin 项目实战--基础 demo
    本章记录一个基础的demo项目,使用kotlin+协程+retrofit+okhttp3+MVVM实现。功能需求调用天气api,在主页显示天气情况。大致流程api申请及实体分析网络请求权限添加kotlin,协程,网络框架等依赖网络框架Retrofit+okhttp3主页页面绘制基础类构建调用接口并显示在当前页面api申请......
  • 运行lucene 的Demo
    这是最简单的方式的lucene的Demo步骤,有稍稍的经验的都应该飘过。step1:下载并安装并配置JDK,具体方法参看我之前的博客:Java环境的搭建 step2: 下载并配置lucene,下载请去:http://labs.renren.com/apache-mirror/lucene/java/ 以我下载的lucene3.0.1为例,下载完后,我们......
  • DXF解析成运动控制指令DEMO源代码,运动控制软件必备模块。 支持
    DXF解析成运动控制指令DEMO源代码,运动控制软件必备模块。支持比例缩放支持按图层解析,各图层可按加工速度、加工参数等分开控制,各图层可选择加工或不加工支持点、直线、圆、圆弧、多段线解析。暂不支持椭圆、样条曲线、文字、填充内容解析。支持任何运动控制平台,接口已预留好,只需增......
  • 物联网平台,物联网源码,物联网上位机,物联网DEMO,物联网开发框架。
    物联网平台,物联网源码,物联网上位机,物联网DEMO,物联网开发框架。这是一个已经商业化的物联网上位机分离出来的框架,c#语言,含有服务器,客户端,数据库,可以直接运行,系统使用三层设计,层次分明,不同账号可见区域不同。框架已经完成了设备、用户、分组的增删改查,操作日志记录,服务器已经完成和......
  • Springboot实现WebSocket
    一、什么是webSocketWebSocket是HTML5下一种新的协议(Websocket协议本质上是一个基于tcp的协议),它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的,WebSocket是一个持久化的协议。二、修改配置文件在application.properties,修改内容为:server.port=......