【问题标题】:How does WebSockets server architecture work?WebSockets 服务器架构如何工作?
【发布时间】:2015-05-12 19:52:40
【问题描述】:

我试图更好地了解服务器端架构如何用于 WebSockets,目标是在嵌入式应用程序中实现它。似乎这里有 3 个不同的服务器端软件组件在起作用:1) 用于服务静态 HTTP 页面并处理升级请求的 Web 服务器,2) 一个 WebSockets 库,例如 libwebsockets,用于处理 WebSockets 通信的“具体细节” , 和 3) 我的自定义应用程序来实际弄清楚如何处理传入的数据。所有这些如何结合在一起?拥有一个单独的 Web 服务器和 WebSocket 处理部件(也称为 WebSocket 服务器/守护程序)是否很常见?

我的应用程序如何与 Web 服务器和/或 WebSockets 库通信以发送/接收数据?例如,对于 CGI,Web 服务器使用环境变量向自定义应用程序发送信息,并使用标准输出接收响应。这里的等效通信系统是什么?还是您通常将 WebSocket 库链接到客户应用程序?但是,Web 服务器与 WebSocket 库 + 自定义应用程序的通信将如何工作?还是全部 3 个组合成一个组件?

这就是我要问的原因。我在内存有限的 Blackfin 处理器上的 uClinux/no MMU 平台上使用 boa Web 服务器。 boa 中没有原生的 WebSocket 支持,只有 CGI。我试图弄清楚如何向其中添加 WebSockets 支持。我更喜欢使用编译的解决方案,而不是解释的东西,如 JavaScript、Python 或 PHP。我当前的应用程序在 CGI 上使用长轮询,它不能为计划的增强提供足够的性能。

【问题讨论】:

    标签: websocket libwebsockets


    【解决方案1】:

    首先,了解如何建立 webSocket 连接非常重要,因为这对 webSocket 连接和您的网络服务器之间的关系非常重要。

    每个 webSocket 连接都以 HTTP 请求开始。浏览器向请求 webSocket 连接的主机/端口发送 HTTP 请求。该请求可能如下所示:

    GET /chat HTTP/1.1
    Host: example.com:8000
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
    Sec-WebSocket-Version: 13
    

    此请求与对该服务器的任何其他 HTTP 请求的区别在于请求中的 Upgrade: websocket 标头。这告诉 HTTP 服务器这个特定的请求实际上是一个发起 webSocket 连接的请求。此标头还允许 Web 服务器区分常规 HTTP 请求和打开 webSocket 连接的请求。这允许在架构中进行一些非常重要的事情,并且完全是故意这样做的。这允许使用完全相同的服务器和端口来为您的 Web 请求和 webSocket 连接提供服务。所需要的只是您的 Web 服务器上的一个组件,该组件在所有传入的 HTTP 连接上查找此 Upgrade 标头,如果找到,它将接管连接并将其转换为 webSocket 连接。

    一旦服务器识别出这个 upgrade 标头,它就会以合法的 HTTP 响应进行响应,但它会向客户端发出信号表明已接受对 webSocket 协议的升级,如下所示:

    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
    

    此时,客户端和服务器都将原始 HTTP 请求中的套接字保持打开状态,并切换到 webSocket 协议。


    现在,针对您的具体问题:

    我的应用程序如何与网络服务器通信和/或 用于发送/接收数据的 WebSockets 库?

    您的应用程序可以使用现代浏览器中内置的 webSocket 支持,并且可以像这样启动 webSocket 连接:

    var socket = new WebSocket("ws://www.example.com");
    

    这将指示浏览器使用与当前网页连接的相同端口启动与www.example.com 的 webSocket 连接。由于浏览器内置 webSocket 支持,上述 HTTP 请求和升级协议由客户端自动为您处理。

    在服务器端,您需要确保您使用的 Web 服务器具有传入的 webSocket 支持,并且支持已启用和配置。因为一个 webSocket 连接一旦建立起来就是一个持续的连接,它根本不遵循 CGI 模型。必须至少有一个长时间运行的进程来处理实时 webSocket 连接。在服务器模型(如 CGI)中,您需要某种 webServer 插件来支持您的 webSocket 连接的这种长时间运行的过程。在像 node.js 这样已经是一个长期运行的进程的服务器环境中,添加 webSockets 在架构上根本没有改变——而只是一个额外的库来支持 webSocket 协议。

    我建议您可能会发现这篇文章很有趣,因为它讨论了从 CGI 样式的单一请求处理到 webSocket 的连续套接字连接的转变:

    Web Evolution: from CGI to Websockets (and how it will help you better monitor your cloud infrastructure)

    如果你真的想坚持使用标准输入/标准输出模型,有一些库可以为你的 webSockets 建模。这是one such library。他们的标语是“这就像二十年后的 CGI,用于 WebSockets”

    我正在尝试弄清楚如何向其中添加 WebSockets 支持。一世 宁愿使用编译的解决方案而不是某些东西 解释如 JavaScript、Python 或 PHP。

    抱歉,我不熟悉那个特定的服务器环境。可能需要进行一些深入的搜索才能找出您的选择。由于 webSocket 连接是连续连接,因此您将需要一个连续运行的进程,该进程可以是 webSocket 连接的服务器端部分。这可以是您的 webServer 中内置的东西,也可以是 webServer 启动并将传入连接转发到的附加进程。

    仅供参考,我在家里有一个基于 Raspberry Pi 的自定义应用程序,它使用 webSockets 与浏览器网页进行实时通信,它工作得很好。我碰巧将 node.js 用于服务器环境和在 webSockets 之上运行的 socket.io 库,以便在 webSockets 之上为我提供更高级别的接口。我的服务器代码会定期检查几个硬件传感器,然后每当有新的/更改的数据要报告时,它就会向任何打开的 webSockets 发送消息,以便连接的浏览器获得传感器读数的实时更新。

    您可能需要一些长时间运行的应用程序,将传入的 webSocket 连接从 Web 服务器传递到您的长时间运行的进程,或者您需要在与 Web 服务器不同的端口上建立 webSocket 连接(因此它们可能是由完全不同的服务器进程处理)在这种情况下,您将拥有一个完全独立的服务器来处理您的 webSocket 请求和套接字(该服务器还必须支持 CORS 以使浏览器能够连接到它,因为它的端口不同于您的网页)。

    【讨论】:

    • 感谢您的详细回复。在您的 Raspberry Pi 项目中,我假设您有一个长期运行的过程来检查传感器?该进程如何与 node.js 通信以将传感器数据发送到网页?这是我试图更好地理解的架构图的一部分。
    • @Jon - 我的 node.js/Raspberry Pi 系统中只有一个长时间运行的进程,这是一个自定义的 node.js 脚本,它既是我的 webServer,也是我检查传感器的逻辑和在任何连接的 webSockets 上发送数据(从技术上讲,它是多个脚本,但都作为一个长时间运行的 node.js 应用程序的一部分运行)。
    • 所以你已经将我的拼图的 3 个部分组合成一个组件。如果您必须让传感器部件作为一个单独的进程运行,您对它的工作方式有何想法?
    • @Jon - 我给了你几个链接到试图链接 CGI 和 webSocket 世界的文章和产品。那将是您理解它的起点。正如我在回答中所描述的那样,最后,您要么需要在仅用于 websocket 连接的单独端口上运行单独的服务器,要么为现有的 webServer 获取某种插件以及如何使用该插件- in 将完全取决于它的设计方式。正如您现在可能看到的那样,CGI 和 webSocket 在架构上有些对立。
    • @allel - 在底层,webSocket 连接是 TCP 连接,就像 HTTP 连接是 TCP 连接一样。您必须使用 webSocket 数据帧和 webSocket 安全性来使用 webSocket 协议。您不能将其用作原始 TCP 连接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-03
    • 1970-01-01
    • 2018-09-10
    • 1970-01-01
    • 1970-01-01
    • 2011-10-02
    相关资源
    最近更新 更多