要荔枝@ 2024-11-05 00:03 采纳率: 50%
浏览 6

PHP使用websocket来实现实时传输出现问题

PHP使用websocket来实现实时传输出现了问题,原本服务器客户端代码都在本地,可以连接上并能发送消息。后面将服务器代码放在云服务器上运行,本地去连接,结果连接不上了。
websocket是依赖Ratche框架实现的,端口我也开放了,就是不知道哪里处了问题,请各位解答。
附上代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
</head>
<body>
    <input id="message" type="text">
    <button id="send">Send</button>
    <hr>
    <div id="timeline"></div>

    <script>
        // 设定URL建立WebSocket连接
        var conn = new WebSocket('ws://服务器地址:25252/chat');
        // 成功建立连接
        conn.onopen = function (e) {
            conn.send('1,Hello!');
            // alert('WebSocket connection ok.');
        };
        // 收到消息
        conn.onmessage = function (e) {
            document.getElementById('timeline').innerText += e.data;
            document.getElementById('timeline').innerHTML += '<br>';
        };
        // 连接出错
        conn.onerror = function (e) {
            alert('WebSocket connection error.');
        }
        // 断开连接
        conn.onclose = function (e) {
            alert('WebSocket connection closed.');
        }
        // 发送消息
        document.getElementById('send').onclick = function () {
            if (!document.getElementById('message').value) return;
            conn.send(document.getElementById('message').value);
            document.getElementById('message').value = '';
        }
    </script>
</body>
</html>


<?php

namespace app\api\controller;

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\App;

require_once  '/www/wwwroot/yxt_test/vendor/autoload.php';
// header("Access-Control-Allow-Origin: *");  
// header("Access-Control-Allow-Headers: *");

/**
 * 私聊模型
 */
class MyChat implements MessageComponentInterface {
    // 用于保存客户端信息
    protected $clients;
    protected $clientsUserIds;

    public function __construct() {
        // 新建SplObjectStorage用于保存对象
        $this->clients = new \SplObjectStorage;
        $this->clientsUserIds = [];
    }

    // $conn是要与服务端建立连接的客户端对象
    public function onOpen(ConnectionInterface $conn) {
        // 向$clients添加建立连接的客户端
        $this->clients->attach($conn);
        $this->clientsUserIds[$conn->resourceId] = $conn;
        // 输出提示,resourceId可以用于标识客户端
        echo "New connection! Id: {$conn->resourceId}\n";
    }

    public function onClose(ConnectionInterface $conn) {
        if (isset($this->clientsUserIds[$conn->resourceId])) {  
            unset($this->clientsUserIds[$conn->resourceId]); // 从映射中删除用户 ID  
        } 
        // 将关闭连接的客户端从$clients中删除
        $this->clients->detach($conn);
        echo "Connection {$conn->resourceId} has disconnected\n";
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        $conn->close();
    }

    // $msg是客户端发送的数据
    public function onMessage(ConnectionInterface $from, $msg) {

        // 假设消息格式是: {"target_id": "targetId", "message": "your message"}  
        // $data = json_decode($msg, true); 
        $data = explode(',',$msg);
        $to = $data[0];
        echo $to."\n";
        // print_r($this->clientsUserIds[$to]);
        $content = $data[1];
        // 遍历所有客户端,转发消息
        if($content&&isset($this->clientsUserIds[$to]))
        $this-> clientsUserIds[$to]->send("Client {$from->resourceId} to {$to}: {$content}");
        else if($content)
        {
            $from ->send("Client {$from->resourceId} to {$from->resourceId}: {$content}");
        }
        else
        echo " message is null && user no exsit";
        // foreach ($this->clients as $client) {
        //     $client->send("Client {$from->resourceId}: {$msg}");
        //     // 也可以选择不转发给发送者自己
        //     // if ($from !== $client) {
        //     //     $client->send("Client {$from->resourceId}: {$msg}");
        //     // }
        // }
        echo "Client {$from->resourceId}: {$msg}\n";
    }
}

class WebSocketServer {  
    public function run() {  
        echo "Server is running...\n";  

        // 在本机的25252端口启动Ratchet应用  
        $app = new App('服务器地址', 25252);  

        // 将上面的留言板应用与 `/chat` 路径关联  
        $app->route('/chat', new MyChat, array('*'));  

        // 启动应用  
        $app->run();  
    }  
}  

// 启动WebSocket服务器  
(new WebSocketServer())->run();  
  • 写回答

1条回答 默认 最新

  • 香格里辣 2024-11-05 00:04
    关注

    以下回复参考:皆我百晓生券券喵儿等免费微信小程序作答:

    根据你的描述和提供的代码,这个问题可能由以下几个原因导致:

    1. 服务器防火墙设置:确保你的云服务器防火墙允许通过 WebSocket 的端口(在你的例子中是 25252)。你可能需要在防火墙规则中添加一条允许该端口的规则。
    2. 服务器 IP 地址或域名:在 WebSocket 连接字符串中,确保你使用的是正确的服务器 IP 地址或域名。如果你使用了本地开发时使用的 IP 地址(如 localhost 或 127.0.0.1),那么在部署到云服务器后,你需要将其替换为云服务器的实际 IP 地址或域名。
    3. 跨域问题:虽然你在代码中设置了允许所有来源的跨域请求,但在某些情况下,浏览器可能会阻止跨域 WebSocket 连接。你可能需要检查浏览器的控制台以查看是否有任何跨域相关的错误消息。确保你的服务器正确配置了跨域策略。
    4. 代码错误:检查你的 MyChat 类中的 onMessage 方法。你使用了 $data = explode(',',$msg) 来解析消息,这假设消息格式是逗号分隔的。如果客户端发送的消息格式不符合这个预期,可能会导致问题。确保客户端和服务器之间的消息格式一致。
    5. 服务器运行状态:确保你的 WebSocket 服务器一直在运行,并且监听正确的端口(在你的例子中是 25252)。你可以尝试在服务器上运行一些诊断命令来检查服务器的状态。

    如果以上步骤都无法解决问题,你可以尝试以下操作来进一步调试:

    • 检查服务器和客户端的日志,看看是否有任何有用的错误信息。
    • 在浏览器中打开开发者工具,查看控制台是否有任何错误消息或警告。
    • 使用工具如 telnetnc 来测试 WebSocket 连接是否可达。
    • 确保你的 PHP 和 Ratchet 框架版本兼容。

    希望这些建议能帮助你解决问题!如果问题仍然存在,请提供更多详细的错误信息或日志,以便进一步分析。

    评论

报告相同问题?

问题事件

  • 创建了问题 11月5日