简单使用 WebSocket 替代 Server-sent Events 的方法

阅读时长 10 分钟读完

在 web 开发中,实时通信是非常重要的一个部分。在很多情况下,我们需要向客户端实时推送数据,比如即时聊天、股票行情等等。在过去,我们常常使用轮询(polling)或者 long-polling 技术来实现实时通信。随着 WebSocket 的普及,现在我们可以使用 WebSocket 来更加方便地实现实时通信,而不需要使用轮询或者 long-polling。

在使用 WebSocket 的时候,我们常常会遇到 Server-sent Events (SSE) 技术。SSE 是一种使用 HTTP 协议进行实时通信的技术,它基于 HTTP,但是可以实现单向的、服务器向客户端的推送。相比较 WebSocket,SSE 更加简单,因为它不需要建立双向的通信连接。但是 SSE 有一些限制,比如只能使用 GET 方法,无法控制 HTTP 头部,只能使用类似 text/event-stream 这样的 MIME 类型等等。

在这篇文章中,我们会介绍一种使用 WebSocket 替代 SSE 的方法。这种方法基于 WebSocket,不需要使用轮询或者 long-polling,而且在很多情况下,它可以取代 SSE 的使用。

使用 WebSocket 实现实时通信

WebSocket 是 HTML5 中的新特性,它可以在客户端和服务器之间建立双向的通信连接。在建立连接之后,服务器和客户端之间可以实时地传输数据,而不需要使用轮询或者 long-polling。

使用 WebSocket 的代码非常简单,可以参考如下的示例:

-- -------------------- ---- -------
--- ------ - --- ---------------------------------

------------- - -------- -- -
  ---------------------- ------------
--

---------------- - -------- ------- -
  --------------------- ---------- ------------
--

-------------- - -------- -- -
  ---------------------- ---------------
--

-------------- - -------- ------- -
  ------------------------ -------- -------
--

在上面的示例中,我们首先创建了一个 WebSocket 对象,然后分别处理了 onopen、onmessage、onclose 和 onerror 事件。当 WebSocket 连接建立成功时,我们会输出 "WebSocket connected";当收到服务器端的消息时,我们会输出 "Received message:",并打印出所接收到的数据;当连接关闭时,我们会输出 "WebSocket disconnected";当发生错误时,我们会输出 "WebSocket error"。

在实际应用中,WebSocket 连接的建立并不是直接通过 URL 地址就可以完成的。我们需要在服务器端设置 WebSocket,然后在客户端通过 WebSocket 对象的方法来建立连接。下面我们将介绍如何在服务器端和客户端分别设置 WebSocket。

服务器端设置 WebSocket

在服务器端我们需要使用一些 WebSocket 的库来支持 WebSocket 的功能。在 Node.js 中,我们可以使用 ws 这个库来设置 WebSocket。在浏览器端,大多数的现代浏览器都已经支持 WebSocket,我们可以直接使用浏览器原生的 WebSocket 对象。

这里我们以 Node.js 为例来介绍如何设置 WebSocket。首先,我们需要安装 ws 这个库,可以使用 npm install 命令来进行安装:

然后,我们在服务器端使用如下代码来设置 WebSocket:

-- -------------------- ---- -------
----- --------- - --------------

----- --- - --- ------------------ ----- ---- ---

-------------------- -------- -------------- -
  ---------------------- ------------

  ---------------- -------- ----------------- -
    --------------------- ---------- ---------
  ---

  -------------- -------- ------- -
    ---------------------- ---------------
  ---

  --------------- ---------
---

在上面的代码中,我们首先使用 require 方法来载入 ws 模块。然后,我们创建了一个 WebSocket.Server 对象,并设置了它的端口为 8080。接着,我们在 'connection' 事件中处理所有的 WebSocket 连接。当连接建立成功时,我们会输出 "WebSocket connected";当收到客户端消息时,我们会输出 "Received message:",并打印出所接收到的数据;当连接关闭时,我们会输出 "WebSocket disconnected"。最后,我们在连接建立成功后向客户端发送了一条消息。

客户端设置 WebSocket

在客户端我们可以直接使用浏览器原生的 WebSocket 对象来进行设置。我们可以使用 new WebSocket(url) 来创建一个 WebSocket 对象,并设置连接的 URL 地址。接下来,我们分别处理 onopen、onmessage、onclose 和 onerror 事件,可以参考如下示例:

-- -------------------- ---- -------
--- ------ - --- ---------------------------------

------------- - -------- -- -
  ---------------------- ------------
--

---------------- - -------- ------- -
  --------------------- ---------- ------------
--

-------------- - -------- -- -
  ---------------------- ---------------
--

-------------- - -------- ------- -
  ------------------------ -------- -------
--

在上面的代码中,我们首先创建了一个 WebSocket 对象,然后分别处理了 onopen、onmessage、onclose 和 onerror 事件。当 WebSocket 连接建立成功时,我们会输出 "WebSocket connected";当收到服务器端的消息时,我们会输出 "Received message:",并打印出所接收到的数据;当连接关闭时,我们会输出 "WebSocket disconnected";当发生错误时,我们会输出 "WebSocket error"。

将 WebSocket 替代 SSE

在一些情况下,我们需要将 WebSocket 替代 SSE 的使用。比如,当使用的服务器不支持 SSE 或者只允许使用 HTTP 协议时,我们就需要使用 WebSocket 来进行实时通信。下面我们介绍一种使用 WebSocket 替代 SSE 的方法。在这种方法中,我们可以通过发送一个特殊的 GET 请求来建立 WebSocket 连接,然后在服务器端将这个请求转换为 WebSocket 连接。

客户端实现

在客户端实现中,我们可以通过设置两个不同的 URL 作为服务器的地址,一个用于建立 WebSocket 连接,一个用于其他的请求。具体的实现可以参考如下代码:

-- -------------------- ---- -------
-- -- --------- --
--- ------ - --- ----------------------------------------

-- -- --- --
--- --- - --- -----------------
--------------- ------------------------------
-----------

------------- - -------- -- -
  ---------------------- ------------

  -- - --------- ---------------------------------
  -------------------------
--

---------------- - -------- ------- -
  --------------------- ---------- ------------
--

-------------- - -------- -- -
  ---------------------- ---------------
--

-------------- - -------- ------- -
  ------------------------ -------- -------
--

在上面的代码中,我们首先通过 WebSocket 对象建立了一个到 'ws://localhost:8080/events' 的连接。然后,我们通过 XMLHttpRequest 对象发送了一条 GET 请求到 'http://localhost:8080/data'(注意这里使用的是 HTTP 协议)。在服务器端,我们会将这个请求转换为 WebSocket 连接。当 WebSocket 连接建立成功后,我们会向服务器发送消息,告诉它我们要接收实时数据。

服务器端实现

在服务器端实现中,我们需要对 GET 请求进行处理,并将这个请求转换为 WebSocket 连接。具体的实现可以参考如下代码:

-- -------------------- ---- -------
----- --------- - --------------
----- ---- - ----------------

----- ------ - -------------------------- ----- ---- -
  -- -------- --- -------- -
    -- -- --- --
    --------------------- --- ----------

    -- - --- ----- --------- --
    ----- --- - --- ------------------ --------- ---- ---
    -------------------- -------- -------------- -
      ---------------------- ------------

      ---------------- -------- ----------------- -
        --------------------- ---------- ---------
      ---

      -------------- -------- ------- -
        ---------------------- ---------------
      ---

      --------------- ---------
    ---

    ---------------------- ----------- ---------------- -------- -------- -
      ---------------------- --- -----
    ---
  - ---- -
    -------------------
    --------------
  -
---

------------------- -------- -- -
  ------------------- --------- ---- ------------------
---

在上面的代码中,我们首先创建了一个 HTTP 服务器。当客户端发送 GET 请求到 '/data' 时,我们会将其转换为 WebSocket 连接。具体的实现是,在处理 GET 请求时,我们创建了一个 WebSocket.Server 对象,并使用 handleUpgrade 方法将其转换为 WebSocket 连接。当 WebSocket 连接建立成功时,我们会输出 "WebSocket connected";当收到客户端消息时,我们会输出 "Received message:",并打印出所接收到的数据;当连接关闭时,我们会输出 "WebSocket disconnected"。最后,我们在连接建立成功后向客户端发送了一条消息。当客户端发送其他的请求时,我们会返回 "OK"。

总结

在本文中,我们介绍了一种使用 WebSocket 实现实时通信的方法,并将其用于替代 Server-sent Events (SSE) 的使用。实际上,这种方法并不仅限于替代 SSE 的使用,它可以被用于许多其他的实时通信场景中。相比较 SSE,WebSocket 更加方便、灵活,而且可以在双向的通信中使用,具有更广泛的适用性。希望这篇文章能够对大家有所帮助,如果您还有其他问题或疑问,可以通过评论区留言,我们会尽快回复。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/649fffb148841e9894c5d344

纠错
反馈