NodeJS,Express 与 Socket.io 交互

Posted

技术标签:

【中文标题】NodeJS,Express 与 Socket.io 交互【英文标题】:NodeJS, Express with Socket.io interaction 【发布时间】:2018-04-25 14:12:41 【问题描述】:

目前正在开发一个同时使用express.jsSocket.io 的Node.JS 后端。应用程序的基础如下所示:

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res)
  res.sendFile(__dirname + '/index.html');
);

io.on('connection', function(socket)
  console.log('a user connected');
);

http.listen(3000, function()
  console.log('listening on *:3000');
);

所以如果我理解正确的话,express.js 处理所有HTTP/HTTPS 请求,而Socket.io 确实处理有关 websocket 的所有交互。所以这是两个完全分离的实体。应用程序启动后,express 部分正在侦听 http 请求,而 socket.io 部分正在侦听 websocket 事件或连接(使用 HTTP 完成连接,使用 HTTP 标头的 websocket 握手)。因为express 实例和socket.io 实例共享同一个HTTP 服务器,所以它们可以使用同一个TCP 连接。

问题:

    我上述当前的理解是否正确? 这 2 个实体是否可以相互交互,如果可以,以何种方式交互?

【问题讨论】:

这些问题都是开放式的。你的理解基本正确。对于第二个问题,这实际上取决于您所说的“交互”是什么意思。 express 和 socket.io 相得益彰,它们都是独立存在的,做的事情也大不相同,但两者可以一起制作一些非常棒的应用程序。 express 发送给用户的 index.html 页面可以包含 socket.io 客户端,然后该客户端可以与您服务器上的 socket.io 一起工作。这将允许通过 socket.io 访问 express 交付的脚本。以这种方式他们确实互动。 我还是很困惑socket.io是什么,我可以集成在mongdb中,从mongodb获取数据,还可以获取身份验证之类的东西 【参考方案1】:

要了解其背后的工作原理,您必须真正了解 socket.io 连接的工作原理,然后才能了解它与您的 http 服务器的关系。

    默认的 socket.io 连接从几个 http 请求开始。这就是 socket.io 客户端与服务器协商以确定两者都可以支持什么的方式。这些 http 请求会发送到您的 node.js Web 服务器(与您用于 Express 的服务器相同)。插入 socket.io 的请求处理程序会拦截这些请求并处理它们,因此它们不会发送到您的 Express 路由。 在像上面这样的几个 http 请求之后,如果双方同意 webSocket 连接可以作为正在进行的 socket.io 连接的基本传输,那么 socket.io 客户端会向服务器发送一个特殊的 http 请求带有一些自定义标题。 http 服务器(还是用于 Express 的同一服务器)接收到这个特殊的 http 请求,socket.io 服务器代码再次拦截该请求并处理它。在这种情况下,它通过对 webSocket 协议的“升级”来响应这个特殊的 http 请求,并且最初作为 http 请求的套接字被转换为 webSocket 协议,并成为一个只使用 webSocket 协议的长寿命套接字。 此时,http web 服务器不再参与进一步的通信。以 http 请求开始的套接字已移交给 socket.io 服务器代码,并且该套接字现在使用 webSocket 协议。此时,客户端或服务器都可以通过该套接字发送消息,并且它们将被另一端的相应代码接收。 现在,socket.io 实际上在 webSocket 之上使用了一个层。虽然底层数据包针对 webSocket 协议进行了格式化,但 socket.io 在 webSocket 之上添加了自己的应用程序层,这意味着您必须在两端都有 socket.io 代码才能使其工作(socket.io 客户端不能与普通的 webSocket 服务器通信,反之亦然)。

所以如果我理解正确的话,express.js 处理所有 HTTP/HTTPS 请求,而 Socket.io 处理所有与 websockets 相关的交互。

有点。 http 服务器(Express 的基础)处理所有传入的 http 请求。这包括将通过 Express 路由的普通 http 请求,但也包括与打开和建立 socket.io 连接相关的 http 请求。这些特殊请求由 socket.io 插入的 http 服务器请求处理程序处理,而不是传递给 Express 处理。

所以这是两个完全分离的实体。

有一个 http 服务器和一些请求处理程序来决定 Express 是否应该处理请求,或者 socket.io 是否应该处理请求。一旦请求被传递给另一个请求,它们几乎是分开的。

但是,有一些点可以相交。例如,如果您使用带有 Express 的会话管理器来设置会话 cookie 或任何其他类型的设置 cookie 的代码,那么这些 cookie 也可用于 socket.io 连接。因此,使用正确的支持代码,socket.io 连接可以访问由 Express 中间件或请求处理程序创建的会话对象(或其他 cookie)。请记住,socket.io 连接以 http 请求开始,因此浏览器通常会随 http 请求发送的任何 cookie 也将用于 socket.io 请求。

应用程序启动后,express 部分正在侦听 http 请求,而 socket.io 部分正在侦听 websocket 事件或连接(连接是通过 HTTP 完成的,websocket 握手使用 HTTP 标头)。

如上所述,http 服务器正在侦听传入的 http 请求,并且 socket.io 和 Express 都有请求处理程序来查看这些传入请求并决定它们是否应该参与处理该请求。一些传入的请求被定向到 socket.io 服务器代码,一些被定向到快速路由处理程序。

因为 express 实例和 socket.io 实例共享同一个 HTTP 服务器,所以它们可以使用同一个 TCP 连接。

它们并不真正共享 TCP 连接。有一个共享的 http 服务器来监听传入的 http 请求。然后将这些请求路由到 socket.io 代码或 express 代码,以根据请求中的数据进行进一步处理。如果是发起 socket.io 连接的 socket.io 请求,则该 TCP 套接字将“升级”到 webSocket 协议,并且只有 socket.io 服务器代码从那时起处理该 TCP 套接字。如果不是 socket.io 请求,则将 http 请求传递给 Express 代码,并根据定义的中间件和路由决定如何处理。

我上面描述的当前理解正确吗?

部分正确,部分不正确。上面有很多细节。

这 2 个实体可以相互交互吗?如果可以,以什么方式交互?

他们共享 http 服务器。他们共享对 cookie 的访问权限。

使用正确的服务器端代码,可以让 http 请求(通常是来自已加载网页的 Ajax 调用)进入 Express 并让该请求处理程序通过其相应的套接字向该特定客户端发送数据。 io 连接。使用某种 cookie 客户端标识符,可以将现有的 socket.io 连接与传入的 http 请求相关联。


我应该补充一点,我上面描述的是,当您将 socket.io 连接到加载网页的同一主机和端口时,事情是如何工作的。这不是必需的。你可以有一个 http 服务器来加载你的所有网页和 web 资源,另一个 http 服务器(在不同的主机/端口组合上)处理传入的 socket.io 请求。在那种情况下,事物的 express 方面实际上与事物的 socket.io 方面无关。它们实际上是不同的服务器,可能不会共享 cookie,等等......

【讨论】:

非常感谢。这真的很有帮助!

以上是关于NodeJS,Express 与 Socket.io 交互的主要内容,如果未能解决你的问题,请参考以下文章

将 Mysql 与 Nodejs 和 Express 一起使用 (node-mysql)

将 AngularJS html5mode 与 nodeJS 和 Express 一起使用

用户未定义:Nodejs/Express + Passport

phonegap ajax 用户身份验证与 nodejs-express-mongodb-passport js

nodejs i18n __与ejs,express不是函数问题

Nodejs+Express创建HTTPS服务器