【问题标题】:Setting up a websocket on Apache?在 Apache 上设置 websocket?
【发布时间】:2013-06-24 10:23:55
【问题描述】:

所以我正在对 websockets 进行一些研究,但有几个问题我似乎无法找到明确的答案:

  • 如何在我的 Linux 服务器上设置 Web 套接字?有 Apache 模块吗?我必须使用 3rd-party PHP 代码或类似代码吗?

  • 除了浏览器兼容性之外,问题 1 中描述的方法是否还有其他我应该注意的缺点?

  • 如何将我的 websocket 安装“升级”到安全的 websocket 安装(ws:// 到 wss://)?如果我的 Apache 服务器上已经设置了 SSL,这会变得更容易还是更困难?

  • 除了 JavaScript 之外,还有什么语言可以用来连接我的网络套接字?

  • Web 套接字的默认请求方法是什么?

【问题讨论】:

  • 现在我已经有几年处理 Web 套接字的经验了,只是提个建议……在这方面 NGINX 比 Apache 好得多。 NGINX 最初是做代理服务器的,所以自然地,它作为代理比 Apache 稳定得多。至于哪一个更好的网络服务器是另一个话题……
  • 你试过 Apache 的 mod_proxy_wstunnel 了吗?您是如何通过 PHP 进行通信的?您是否使用任何 3rd 方库来执行此操作?
  • 再一次,根据我的经验,NGINX 更适合代理 wstunnel。我确实尝试了 mod_proxy_wstunnel 并且它运行良好,但它导致连接保持打开数天出现问题。我一开始使用 PHP,不记得我用了什么,但现在我用 C 编写我的 Web 套接字后端,而 C 非常适合处理套接字。 PHP 不是长期作为进程运行的。 socketo.me 是 PHP Web 套接字服务器的一个很好的参考。 developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/… 是帮助学习的好指南。

标签: apache websocket


【解决方案1】:

我无法回答所有问题,但我会尽力而为。

如您所知,WS 只是一个持久的全双工 TCP 连接,带有帧消息,其中初始握手类似于 HTTP。您需要一些服务器来监听传入的 WS 请求并将处理程序绑定到它们。

现在使用 Apache HTTP Server 可能是可行的,并且我已经看到了一些示例,但是没有官方支持并且变得复杂。阿帕奇会做什么?你的处理程序在哪里?有一个模块可以将传入的 WS 请求转发到外部共享库,但这对于使用 WS 的其他出色工具来说不是必需的。

WS 服务器趋势现在包括:Autobahn(Python)和Socket.IO(Node.js = 服务器上的 JavaScript)。后者还支持其他骇人听闻的“持久”连接,例如长轮询和所有COMET 的东西。还有其他鲜为人知的 WS 服务器框架,例如 Ratchet(PHP,如果您只熟悉它的话)。

在任何情况下,您都需要监听一个端口,当然该端口不能与您机器上已经运行的 Apache HTTP 服务器相同(默认值 = 80)。您可以使用 8080 之类的东西,但即使这个特定的选择是一个流行的选择,一些防火墙可能仍然会阻止它,因为它不应该是 Web 流量。这就是为什么许多人选择 443,这是 HTTP 安全 端口,出于显而易见的原因,防火墙不会阻止该端口。如果您不使用 SSL,则可以将 80 用于 HTTP,将 443 用于 WS。 WS 服务器不需要是安全的;我们只是在使用端口。

编辑:根据 Iharob Al Asimi 的说法,前一段是错误的。我没有时间对此进行调查,因此请查看他的工作以了解更多详细信息。

关于协议,如Wikipedia shows,是这样的:

客户端发送:

GET /mychat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://example.com

服务器回复:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

并保持连接有效。如果您可以实现这种握手和基本消息框架(用描述它的小标题封装每条消息),那么您可以使用任何您想要的客户端语言。 JavaScript 仅用于 Web 浏览器,因为它是内置的。

如您所见,默认的“请求方法”是初始 HTTP GET,尽管这并不是真正的 HTTP,并且在握手之后失去了与 HTTP 的所有共同点。我猜服务器不支持

Upgrade: websocket
Connection: Upgrade

将回复错误或页面内容。

【讨论】:

  • 感谢您的意见。昨晚我一直在摆弄这个,你的回答帮助我理解了一些事情。虽然它不能回答所有问题,但它绝对为我指明了正确的方向。我可能会使用 Rachet,因为服务器已经在运行 PHP。我想我目前最大的问题是“为什么 websocket 默认端口与默认 HTTP 端口重叠?”。
  • 因为它旨在与 HTTP 服务器集成。但是,我不认为 Apache HTTP Server 目前有一种简单的方法可以做到这一点。但是使用上述框架,也应该很容易提供 HTTP 服务,因此您可以完全放弃 Apache HTTP Server。您将需要为不同的上下文路径提供不同的处理程序(例如,/myWsEndpoint 导致 WS 处理程序,/hello 导致 HTTP 端点)。另外我忘了提到Jetty,这对 Java 程序员来说非常好和容易(同时服务于 HTTP 和 WS)。
  • 我明白了。感谢您所有的帮助。下班后我会做更多的实验。
  • 我投反对票,因为 当然它可以是 apache 用于常规 HTTP 的相同端口
  • 事实上,我成功地编写了一个 apache 模块来处理 WS 协议握手并与另一个程序进行通信,用您的话说就是“处理程序”。这真的很容易,而且很强大。哦,它使用端口 80。实际上这是 javascript websocket API 中的默认值。
【解决方案2】:

Apache HTTP Server 的新版本 2.4 有一个名为 mod_proxy_wstunnel 的模块,它是一个 websocket 代理。

http://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html

【讨论】:

  • 您需要启用mod_proxymod_proxy_wstunnel模块并在httpd.conf文件中添加ProxyPass /wss2/ ws://YOUR_DOMAIN:WS_PORT/。在 JS 调用中使用不带端口号 url 的安全方案(例如 var ws = new WebSocket("wss://YOUR_DOMAIN/wss2/NNN"); See Ref
  • 这个完全支持websocket吗
【解决方案3】:

我很难理解 https 的 websockets 的代理设置,因此让我在这里澄清一下我所意识到的。

首先您需要启用proxyproxy_wstunnel apache 模块,apache 配置文件将如下所示。

<IfModule mod_ssl.c>
    <VirtualHost _default_:443>
      ServerName www.example.com
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/your_project_public_folder

      SSLEngine on
      SSLCertificateFile    /etc/ssl/certs/path_to_your_ssl_certificate
      SSLCertificateKeyFile /etc/ssl/private/path_to_your_ssl_key

      <Directory /var/www/your_project_public_folder>
              Options Indexes FollowSymLinks
              AllowOverride All
              Require all granted
              php_flag display_errors On
      </Directory>
      ProxyRequests Off 
      ProxyPass /wss/  ws://example.com:port_no

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>
</IfModule>

在您的前端应用程序中使用 url "wss://example.com/wss/" 这非常重要,如果您坚持使用 websockets,您可能会在前端 url 中出错。你可能把 url 放错了,如下所示。

wss://example.com:8080/wss/ -> port no should not be mentioned
ws://example.com/wss/ -> url should start with wss only.
wss://example.com/wss -> url should end with / -> most important

另一个有趣的部分是最后一个/wss/proxypass 值相同,如果你写proxypass /ws/,那么在前端你应该在url 的末尾写/ws/

【讨论】:

    猜你喜欢
    • 2016-04-12
    • 1970-01-01
    • 2023-04-09
    • 2010-10-01
    • 2019-07-02
    • 1970-01-01
    • 2014-04-04
    • 2018-11-11
    • 2015-05-28
    相关资源
    最近更新 更多