websockets 连接因 apache 和 Ratchet 而失败

websockets connections fail with apache and Ratchet

我使用 Ratchet that I call with javascript using the websocket object.

库编写了一个 php websockets 服务器

一切都在本地完美运行,但不可能 运行 我的项目在我的 Debian 服务器上使用 apache。

要启用 websocket 连接,我读到我必须使用 mod_proxy_wstunnel 模块。所以我为我的子域 api.domain.com 重写了我的 apache conf,如下所示:

<VirtualHost *:80>
        ServerAdmin admin@admin.admin
        DocumentRoot /var/www/api.domain.com
        ServerName api.domain.com

        # Enable Websocket connections on port 8888
        ProxyPass "/wss/homews/" "ws://api.domain.com:8888/"

        <Directory /var/www/api.domain.com>
                Options FollowSymLinks
                AllowOverride All
                Order allow,deny
                Allow from all
                Satisfy all
        </Directory>
</VirtualHost>

然后我使用启动 Ratchet websocket 服务器的代码洞察调用我的 php 脚本:

// ...
// Some code ...
$app = new Ratchet\App('localhost', 8888);
$app->route('/wss/homews/', $myClass, array('*'));
$app->run();

然后当我尝试在 javascript 客户端使用 url ws://api.domain.com:8888/wss/homews/ 连接到它时,我总是得到 Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT.

您知道我该如何调试此类错误吗? apache 上是否有任何日志显示配置错误?

首先,尽量简化事情,不要编辑或触摸服务器上的任何配置文件,默认情况下保持原样,就可以了

我会post所有的socket up和运行ning需要的注意事项,请大家一步一步来,如下:

  1. 检查您的服务器是否支持共享主机上的 Web Socket,否则您可能需要使用专用主机服务或虚拟专用服务器(VPS) 例如:AWS、GCP。 如果您的服务器支持 运行 在 Web 服务中使用 phpwebsocket 等 Web 服务脚本,请执行后续步骤

  2. 在终端,更新作曲家到最新的,然后尝试执行$composer require cboden/ratchet 这样所需的依赖项将有效地加载,并且不要尝试上传任何存档的依赖项。 在我的例子中,"cboden/ratchet": "^0.4.3" 被加载到本地主机上,但在生产站点上它是 "cboden/ratchet": "^0.4.1" 比较 composer.json 文件

  3. 尝试连接到8282端口,在大多数情况下,服务器流量,入站和出站流量默认保持打开,以防8080端口无法绑定到TCP

  4. 最后,尝试重启您的云托管服务器实例并执行 websocket 脚本 $php <yourWebSocketScript.php>

我曾使用 mod_proxy_wstunnel 来确保通信加密,除此之外, 我能够在 AWS 和我们的私人专用服务器上顺利启动 & 运行 Websocket socketo.me

感谢您的联系,我非常感谢您的努力,除了您通过 johannchopin@protonmaildotcom 回复的关注评论外,这不是我的商业道德部分


编辑

$app = new Ratchet\App('localhost', 8888);
$app->route('/wss/homews/', $myClass, array('*'));
$app->run();

尝试将上面代码段中的 <yourWebSocketScript.php> 手动分配的 localhost 更改为

$app = IoServer::factory(
    new HttpServer(new WsServer(new Chat())),
    8282
);
$app->run();

尝试绑定到 HttpServer,它默认为 localhost0.0.0.0 和 运行(如有必要,删除 $app->route()

你的代码需要修改

  1. yourWebSocketScript.php

  2. 中的端口号
  3. localhost更改为someChatFilexyz.php

  4. 中的服务器IP或DNS
    Eg:
    let websocket_server = new WebSocket("ws://my.domain.com:8282");
    or
    let websocket_server = new WebSocket("ws://xxx.xxx.xxx.xxx:8282");
  1. kill所有之前建立的特定于8282端口的socket然后运行yourWebSocketScript.php

这是someChatFilexyz.php

的部分代码
jQuery(function($){
// Websocket_Controller
var websocket_server = new WebSocket("ws://xxx.xxx.xxx.xxx:8282");
websocket_server.onopen = function(e) {
websocket_server.send(
...
);
};

websocket_server.onerror = function(e) {
// Errorhandling
...
}

websocket_server.onmessage = function(e) {

...
}
}

设置上述配置后,我能够 运行 在 Amazon Web Service 上使用我配置的 LAMP 堆栈和私人专用服务器轻松地进行。

注意:代码中的任何微小更改,您都需要重新启动 运行ning websocket 脚本 $php <yourWebSocketScript.php> 即,终止 运行ning 进程或终止特定进程分配给端口号

您的上述配置至少要更改为:

<VirtualHost *:80>
        ServerAdmin admin@admin.admin
        DocumentRoot /var/www/api.domain.com
        ServerName api.domain.com

        # Enable Websocket connections on port 8888
        ProxyPass "/wss/homews/" "ws://localhost:8888/wss/homews/"

        <Directory /var/www/api.domain.com>
                Options FollowSymLinks
                AllowOverride All
                Order allow,deny
                Allow from all
                Satisfy all
        </Directory>
</VirtualHost>

并在 javascript 客户端到 url ws://api.domain.com:80/wss/homews/

否则可能(或者说希望用于服务器设置)来自网络服务器配置 api.domain.com:8888 的目标试图到达服务器 public IP 上的 websocket 上游,而 websocket 绑定到本地主机。第八,它只是不在那里听(这很好,因为你通常只想将你的网络服务器端口暴露给 public 而不是直接暴露给你的应用程序端口)或者更糟糕的是它试图到达一个 public NAT IP which涉及到应该阻止端口 8888 的防火墙之旅,这可能不允许这些东西,可能很昂贵(例如 AWS EC2)并且至少性能不佳。

另一方面,您需要将客户端代码定向到端口 80 上的网络服务器,该端口会与您的 websocket 应用建立隧道,因此您的客户端无法直接访问服务器的端口 8888(它在 public 防火墙希望 - 你正在听本地主机)。

尝试使用您的原始设置并说明结果如何变化,也许还有其他问题(但您至少不应再出现套接字超时以及从客户端到 websocket 应用程序的连接)。