首页
Preview

使用Socket.io和React构建一个Node.js WebSocket聊天应用程序

WebSockets 在构建实时通信或数据流应用程序方面非常有益,例如聊天应用程序和流媒体图像或其他类型的媒体应用程序。此外,你可以使用浏览器的 JavaScript WebSocket API 轻松地建立到任何套接字端点的连接。

在本教程中,我们将使用 socket.ioReact 构建一个基于 WebSockets 的简单聊天应用程序。和往常一样,完整的源代码在这里可用。

为什么要使用 WebSockets 而不是 HTTP(S)?

使用 WebSockets,你可以建立一个持久连接,允许客户端和服务器之间进行双向通信。现在,在 web 上,你主要会发现基于 HTTP 的 REST API。这些 API 的使用方式如下:客户端请求页面或资源,服务器响应(请求-响应)。因此,使用 WebSockets 而不是 HTTP 可以具有以下优点:

1. 实时通信

在请求-响应场景中,服务器没有办法在客户端没有请求任何内容的情况下向客户端发送数据。客户端将不得不连续不断地请求常规间隔中的更改(轮询),这不是我们所考虑的实时。想象一下聊天应用程序,你只能每 30 秒看到新消息。相当烦人...

有几种方法可以让服务器通过 HTTP 消息通知客户端新事件。你可以将消息推送到运行在客户端浏览器中的服务工作者或让客户端订阅服务器发送事件SSE)。但是,使用 WebSockets,我们可以免费获得此功能,并可以轻松地将接收到的新消息广播到每个其他连接的客户端。

2. 减少开销

HTTP 是一种无状态协议,因此在每个消息中添加了 HTTP 标头的开销可能会非常大。这将特别影响具有相对较小有效负载的频繁消息(例如聊天应用程序)。

此外,HTTP 连接通常仅保持活动状态一定数量的请求,并且在闲置一段时间后将关闭。因此,连接将经常必须重新建立,这会由于 TCP 三次握手(在 HTTPS 的情况下还涉及交换证书和密钥对)而引入初始设置时间。

3. 流处理

使用 WebSockets,你可以在客户端和服务器之间本质上流式传输任意大小的二进制数据。因此,它非常适合流处理任务,例如可能会来回流式传输图像或视频数据的图像处理应用程序。

最后让我们编写应用程序吧!

我们将使用 socket.io npm 包,该包为我们的聊天服务器提供了一个 node.js WebSocket API,为浏览器端提供了 JavaScript 客户端。这样,我们就不必费心地发送实际的二进制数据,因为此包将把我们的数据友好地序列化为 JSON。

监听传入的套接字连接

在此示例中,我们将将 socket.io 附加到一个简单的 HTTP 服务器。如果你愿意,你也可以轻松地将 socket.io 与 express 结合使用。

使用 io.on('connection', cb) 我们正在侦听传入的套接字连接。一旦有新客户端连接,我们可以将多个事件侦听器附加到流中。 errordisconnect 事件是预定义的。其他事件是我引入的自定义事件,以实现聊天 API。

服务器正在侦听套接字客户端在端口 3000 上连接,我们将在下面执行此操作。

使用客户端连接套接字服务器

请注意,在客户端上,我们要求 socket.io-client。如果你不使用打包程序(我在这里使用 webpack),则必须将 io 客户端脚本包含到文档中。

在客户端中,我们可以使用 socket.on 监听事件,并使用 socket.off 删除事件侦听器。稍后,我们将使用 registerHandler 在我们的 Chatroom 组件中注册 onMessageReceived 回调,以便在接收到新消息时更新组件状态并显示新消息。

使用 socket.emit,我们可以发出自定义事件,我们的聊天服务器侦听。作为第二个参数,我们可以传递实际数据。此外,我们甚至可以通过将回调作为第三个参数传递来实现请求-响应类型的通信,我们可以在向客户端发出事件或另一种方式时使用该回调从聊天服务器接收响应。这很棒,我们稍后将在此示例中经常使用它。

实现 API

在我们的聊天服务器上,我们将跟踪所有连接的客户端以及他们选择的角色(ClientManager),以及每个聊天室的状态,例如加入聊天室的用户列表和发送到该聊天室的所有消息的历史记录(ChatroomManager)。

我们要添加的第一件事是一个用于客户端选择其中一个角色的端点:

我们将坚持使用callback(error, result)模式,并在出现错误时将错误消息作为第一个参数调用回调。在这里,我们要做的是检查所选角色是否可用并将客户端分配给该角色,否则使用错误消息通知客户端。当用户加入、离开聊天室或发送消息时,会发生更有趣的事情。对应的事件处理程序使用以下辅助函数:

它确保传递的聊天室有效,并且在事先选择了一个角色并添加了“用户离开/加入聊天室”或用户发送的消息到聊天室的聊天历史记录中。此外,我们将事件广播到聊天室中的所有用户。

Chatroom 的实现相当简单:

为了简单起见,chatHistory 只是一个数组,我们保存了该聊天室中所有用户的映射,以便我们可以在 broadcastMessage 中向所有客户端发出“message”事件。

由于实际处理程序相互类似,因此我将仅在此处显示加入处理程序:

处理事件后,我们将用户添加到聊天室并响应当前聊天历史记录。

最后,一旦客户端断开连接,我们还确保从所有聊天室中删除用户并删除客户端信息,这将释放角色的选择,以供其他用户使用:

在客户端实时显示消息

对于我们的聊天室组件,我们添加以下内容:

一旦进入新的聊天室,我们就会初始化聊天服务器返回的聊天历史记录,接收“join”事件后。如前所述,当组件挂载时,我们在客户端 API 的处理程序中注册 onMessageReceived 回调函数。一旦注册,客户端将接收聊天服务器广播的消息事件。这样,我们就可以使用新消息更新组件状态,并立即重新渲染聊天活动。

版权声明:本文内容由TeHub注册用户自发贡献,版权归原作者所有,TeHub社区不拥有其著作权,亦不承担相应法律责任。 如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

点赞(0)
收藏(0)
一个人玩
先找到想要的,然后出发

评论(0)

添加评论