单聊

2024-11-11 14:01   42   0  

 开发一个聊天应用(包括单聊和群聊)涉及多个组件和技术。下面是一个基于 Hyperf 框架的简单示例,展示如何实现基本的单聊和群聊功能。


### 1. 环境准备


首先,确保你已经安装了 Hyperf 框架,并且配置好了相关依赖。你可以使用 Composer 来安装 Hyperf:


```sh

composer create-project hyperf/hyperf-skeleton your-project-name

cd your-project-name

```


### 2. 安装 WebSocket 组件


Hyperf 提供了 WebSocket 组件,可以方便地实现 WebSocket 服务器。安装 WebSocket 组件:


```sh

composer require hyperf/websocket-server

```


### 3. 配置 WebSocket 服务


在 `config/autoload/server.php` 中添加 WebSocket 服务配置:


```php

return [

    'servers' => [

        [

            'name' => 'http',

            'type' => Server::SERVER_HTTP,

            'host' => '0.0.0.0',

            'port' => 9501,

            'sock_type' => SWOOLE_SOCK_TCP,

            'callbacks' => [

                Event::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'],

            ],

        ],

        [

            'name' => 'websocket',

            'type' => Server::SERVER_WEBSOCKET,

            'host' => '0.0.0.0',

            'port' => 9502,

            'sock_type' => SWOOLE_SOCK_TCP,

            'callbacks' => [

                Event::ON_HAND_SHAKE => [Hyperf\WebSocketServer\Server::class, 'onHandShake'],

                Event::ON_MESSAGE => [App\Controller\WebSocketController::class, 'onMessage'],

                Event::ON_CLOSE => [App\Controller\WebSocketController::class, 'onClose'],

            ],

        ],

    ],

];

```


### 4. 创建 WebSocket 控制器


在 `app/Controller` 目录下创建 `WebSocketController.php` 文件:


```php

<?php


declare(strict_types=1);


namespace App\Controller;


use Hyperf\WebSocketServer\Frame;

use Hyperf\WebSocketServer\Server as WebSocketServer;

use Swoole\WebSocket\Server as SwooleWebSocketServer;


class WebSocketController

{

    public function onMessage(SwooleWebSocketServer $server, Frame $frame)

    {

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

        if (isset($data['type'])) {

            switch ($data['type']) {

                case 'single_chat':

                    $this->handleSingleChat($server, $frame, $data);

                    break;

                case 'group_chat':

                    $this->handleGroupChat($server, $frame, $data);

                    break;

                default:

                    // 处理未知类型的消息

                    break;

            }

        }

    }


    private function handleSingleChat(SwooleWebSocketServer $server, Frame $frame, array $data)

    {

        if (isset($data['to']) && isset($data['message'])) {

            $toFd = $this->getUserFd($data['to']);

            if ($toFd !== null) {

                $server->push($toFd, json_encode([

                    'type' => 'single_chat',

                    'from' => $frame->fd,

                    'message' => $data['message'],

                ]));

            }

        }

    }


    private function handleGroupChat(SwooleWebSocketServer $server, Frame $frame, array $data)

    {

        if (isset($data['group']) && isset($data['message'])) {

            $groupFds = $this->getGroupFds($data['group']);

            foreach ($groupFds as $fd) {

                $server->push($fd, json_encode([

                    'type' => 'group_chat',

                    'from' => $frame->fd,

                    'message' => $data['message'],

                ]));

            }

        }

    }


    private function getUserFd(string $username): ?int

    {

        // 这里假设你有一个用户到 FD 的映射表

        // 实际应用中,你可以使用 Redis 或其他存储来管理这个映射

        return $this->userFdMap[$username] ?? null;

    }


    private function getGroupFds(string $groupName): array

    {

        // 这里假设你有一个组到 FD 列表的映射表

        // 实际应用中,你可以使用 Redis 或其他存储来管理这个映射

        return $this->groupFdMap[$groupName] ?? [];

    }


    public function onClose(SwooleWebSocketServer $server, int $fd)

    {

        // 处理连接关闭事件

        // 例如,从用户到 FD 的映射表中移除该用户

    }

}

```


### 5. 用户和组的管理


为了管理用户和组,你可以使用 Redis 或其他存储来保存用户到 FD 的映射和组到 FD 列表的映射。这里是一个简单的示例,使用数组来模拟:


```php

class WebSocketController

{

    private $userFdMap = [];

    private $groupFdMap = [];


    public function onOpen(SwooleWebSocketServer $server, \Swoole\Http\Request $request)

    {

        // 假设客户端在连接时发送了一个包含用户名和组名的 JSON 数据

        $data = json_decode($request->rawContent(), true);

        if (isset($data['username'])) {

            $this->userFdMap[$data['username']] = $request->fd;

        }

        if (isset($data['group'])) {

            $this->groupFdMap[$data['group']][] = $request->fd;

        }

    }


    // 其他方法...

}

```


### 6. 客户端示例


客户端可以使用 JavaScript 的 WebSocket API 来连接服务器并发送消息。以下是一个简单的 HTML 页面示例:


```html

<!DOCTYPE html>

<html>

<head>

    <meta charset="UTF-8">

    <title>Chat Application</title>

</head>

<body>

    <input type="text" id="username" placeholder="Username">

    <input type="text" id="group" placeholder="Group">

    <button onclick="connect()">Connect</button>

    <input type="text" id="message" placeholder="Message">

    <button onclick="sendMessage()">Send</button>

    <div id="messages"></div>


    <script>

        let socket;


        function connect() {

            const username = document.getElementById('username').value;

            const group = document.getElementById('group').value;

            socket = new WebSocket('ws://localhost:9502');


            socket.onopen = () => {

                socket.send(JSON.stringify({ username, group }));

            };


            socket.onmessage = (event) => {

                const messagesDiv = document.getElementById('messages');

                messagesDiv.innerHTML += `<p>${event.data}</p>`;

            };

        }


        function sendMessage() {

            const message = document.getElementById('message').value;

            socket.send(JSON.stringify({

                type: 'single_chat', // 或 'group_chat'

                to: 'target_username', // 对于单聊

                group: 'target_group', // 对于群聊

                message

            }));

        }

    </script>

</body>

</html>

```


### 7. 运行项目


启动 Hyperf 项目:


```sh

php bin/hyperf.php start

```


打开浏览器,访问你的 HTML 页面,连接 WebSocket 服务器并发送消息。


### 总结


以上是一个基于 Hyperf 框架的简单聊天应用示例,包括单聊和群聊功能。实际应用中,你可能需要处理更多的细节,例如用户认证、消息存储、错误处理等。希望这个示例对你有帮助!如果有任何问题,请随时提问。


上一篇
没有了
博客评论
还没有人评论,赶紧抢个沙发~
发表评论
说明:请文明发言,共建和谐网络,您的个人信息不会被公开显示。