理解 PHP 中的 WebSockets

WebSockets 通过单个 TCP 连接提供全双工通信通道。对于聊天应用程序、实时通知和协作工具等实时通信应用程序来说,它们非常方便。本文将探讨如何在 PHP 中实现 WebSockets。

为什么要使用 WebSockets?

传统的 HTTP 是一种请求-响应协议,对于实时应用程序来说效率不高,因为客户端必须反复轮询服务器以检查更新。另一方面,WebSockets 建立了一个持久连接,允许数据双向流动,而无需多个 HTTP 请求的开销。

使用 Ratchet 设置 WebSocket 服务器

要在 PHP 中设置 WebSocket 服务器,我们将使用 Ratchet 库,它是处理 WebSocket 连接的常用 PHP 库。下面介绍如何开始:

前提条件

  • PHP 7.0 或更高版本
  • Composer – PHP 依赖关系管理工具

步骤 1:安装 Ratchet

首先,我们需要使用 Composer 安装 Ratchet。如果没有安装 Composer,可以从 getcomposer.org 下载。

composer require cboden/ratchet

步骤 2:创建 WebSocket 服务器

新建一个名为 server.php 的 PHP 文件,并添加以下代码:

<?php
require 'vendor/autoload.php';

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

class Chat implements MessageComponentInterface {
    protected $clients;

    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }

    public function onOpen(ConnectionInterface $conn) {
        // Store the new connection
        $this->clients->attach($conn);
        echo "New connection! ({$conn->resourceId})\n";
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        $numRecv = count($this->clients) - 1;
        echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
            , $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');

        foreach ($this->clients as $client) {
            if ($from !== $client) {
                // Send the message to all clients except the sender
                $client->send($msg);
            }
        }
    }

    public function onClose(ConnectionInterface $conn) {
        // The connection is closed, remove it from the clients list
        $this->clients->detach($conn);
        echo "Connection {$conn->resourceId} has disconnected\n";
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "An error has occurred: {$e->getMessage()}\n";
        $conn->close();
    }
}

// Run the server
$server = \Ratchet\App::factory(function () {
    $loop = React\EventLoop\Factory::create();
    $pusher = new Chat();

    // Listen for the 'Chat' application on port 8080
    $webSock = new React\Socket\Server('0.0.0.0:8080', $loop);
    $webServer = new Ratchet\Server\IoServer(
        new Ratchet\Http\HttpServer(
            new Ratchet\WebSocket\WsServer(
                $pusher
            )
        ),
        $webSock
    );

    $loop->run();
}, 8080, '0.0.0.0');

echo "WebSocket server running at ws://localhost:8080\n";

步骤 3:运行 WebSocket 服务器

使用 PHP CLI 运行 WebSocket 服务器:

php server.php

该命令将启动 WebSocket 服务器,监听 ws://localhost:8080 上的连接。

步骤 4:创建 WebSocket 客户端

要与 WebSocket 服务器交互,我们需要一个客户端。创建一个名为 client.html 的 HTML 文件,并添加以下代码:

<!DOCTYPE html>
<html>
<head>
    <title>WebSocket Client</title>
</head>
<body>
    <h1>WebSocket Client</h1>
    <input type="text" id="message" placeholder="Type a message..." />
    <button onclick="sendMessage()">Send</button>
    <ul id="messages"></ul>

    <script>
        var conn = new WebSocket('ws://localhost:8080');

        conn.onopen = function(e) {
            console.log("Connection established!");
        };

        conn.onmessage = function(e) {
            var messages = document.getElementById('messages');
            var message = document.createElement('li');
            message.textContent = e.data;
            messages.appendChild(message);
        };

        function sendMessage() {
            var input = document.getElementById('message');
            var msg = input.value;
            conn.send(msg);
            input.value = '';
        }
    </script>
</body>
</html>

步骤 5:测试 WebSocket 连接

  • 在 Web 浏览器中打开 client.html 文件。
  • 打开开发者控制台查看连接日志。
  • 输入一条信息,然后点击 “发送”。

如果打开多个浏览器窗口,信息会出现在所有窗口中,这表明 WebSockets 实现了实时通信。

使用 Swoole 设置 WebSocket 服务器

前提条件

  • PHP 7.2 或更高版本
  • Swoole PHP 扩展

安装 Swoole

如果尚未安装 Swoole,可使用以下命令进行安装:

pecl install swoole

确保在 php.ini 文件中启用了 Swoole 扩展:

extension=swoole

步骤 1:使用 Swoole 创建 WebSocket 服务器

创建名为 swoole_server.php 的 PHP 文件并添加以下代码:

<?php
use Swoole\WebSocket\Server;

$server = new Server("0.0.0.0", 9502);

$server->on('open', function (Server $server, $request) {
    echo "Connection opened: {$request->fd}\n";
});

$server->on('message', function (Server $server, $frame) {
    echo "Received message: {$frame->data}\n";
    foreach ($server->connections as $fd) {
        $server->push($fd, $frame->data);
    }
});

$server->on('close', function ($server, $fd) {
    echo "Connection closed: {$fd}\n";
});

$server->start();

步骤 2:运行 WebSocket 服务器

使用 PHP CLI 运行 WebSocket 服务器:

php swoole_server.php

该命令将启动 WebSocket 服务器,监听 ws://localhost:9502 上的连接。

步骤 3:创建 WebSocket 客户端

要与 WebSocket 服务器交互,请创建一个名为 client.html 的 HTML 文件并添加以下代码:

<!DOCTYPE html>
<html>
<head>
    <title>WebSocket Client</title>
</head>
<body>
  <h1>WebSocket Client</h1>
  <input type="text" id="message" placeholder="Type a message..." />
  <button onclick="sendMessage()">Send</button>
  <ul id="messages"></ul>
  <script>
        var conn = new WebSocket('ws://localhost:9502');
        conn.onopen = function(e) {
            console.log("Connection established!");
        };
        conn.onmessage = function(e) {
            var messages = document.getElementById('messages');
            var message = document.createElement('li');
            message.textContent = e.data;
            messages.appendChild(message);
        };
        function sendMessage() {
            var input = document.getElementById('message');
            var msg = input.value;
            conn.send(msg);
            input.value = '';
        }
  </script>
</body>
</html>

步骤 4:测试 WebSocket 连接

  • 在Web浏览器中打开 client.html 文件。
  • 打开开发者控制台查看连接日志。
  • 在输入框中键入一条信息,然后点击 “发送”。

如果打开多个浏览器窗口,信息会出现在所有窗口中,这表明 WebSockets 实现了实时通信。

确保 WebSockets 连接的安全

要确保 PHP 中 WebSocket 连接的安全,请按以下步骤操作:

  • 使用 wss:// 而不是 ws://:在建立 WebSocket 连接时,使用 wss:// 协议而不是 ws://。这将通过加密数据为通信增加一个安全层。
  • 使用 Nginx 进行反向代理:使用 Nginx 等服务器建立反向代理来处理 WebSocket 连接,并在 WebSocket 连接上启用 SSL 以确保通信安全。

服务器端安全检查:

  • 在服务器端实施安全检查(客户端检查是为了用户体验,而非安全性)。
  • 确保无法猜测会话 ID。
  • 清理不再使用的会话。
  • 如果符合您的使用情况,考虑强制执行每个用户一个会话和每个会话一个 WebSocket 连接。

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论