长轮询或全双工连接?问题在哪里?

Long Polling or full-duplex connection? Where is the catch?

我正在实施一个带有长轮询的消息传递系统,以便为我的用户提供实时更新。 这样做我注意到一些网站如 Hotmail 也使用 xhr 请求,但它们似乎与我实现的有点不同。

如图所示,在我的实现中,客户端发出请求,服务器保留请求,直到有新的数据更新可用。然后发回有效负载并关闭连接。收到后,javascript 向网络服务器发送一个新请求。

Hotmail 在保持连接打开的同时发回请求。这怎么可能??我该如何自己实施呢?最重要的是,有什么区别?

谢谢。

有两种最常见的双向 HTTP 机制,请参阅 RFC6202 "Known Issues and Best Practices for the Use of Long Polling and Streaming in Bidirectional HTTP":

  • HTTP Long Polling: The server attempts to "hold open" (not immediately reply to) each HTTP request, responding only when there are events to deliver. In this way, there is always a pending request to which the server can reply for the purpose of delivering events as they occur, thereby minimizing the latency in message delivery.

  • HTTP Streaming: The server keeps a request open indefinitely; that is, it never terminates the request or closes the connection, even after it pushes data to the client.

您还可以在 RFC6202 中找到这些方法的详细问题列表。这些方法中的每一种都有其优点和缺点。

因此,在 HTTP 流传输期间,连接不会终止:

The basic life cycle of an application using HTTP streaming is as follows:

  1. The client makes an initial request and then waits for a response.

  2. The server defers the response to a poll request until an update is available, or until a particular status or timeout has occurred.

  3. Whenever an update is available, the server sends it back to the client as a part of the response.

  4. The data sent by the server does not terminate the request or the connection. The server returns to step 3.

我认为可能有比使用长轮询更好的方法。您可以实现 WebSocket 连接。然后,您就有了到服务器的持久双向连接。 WebSocket 是一种基于 HTTP 的升级协议,旨在避免“某种变通方法”——如长轮询之类的技巧。 如果你想阅读更详细的内容:

https://www.rfc-editor.org/rfc/rfc6455

http://www.html5rocks.com/en/tutorials/websockets/basics/

如果您想支持无法建立 WebSocket 的旧浏览器,您可以使用 Dojox/Socket 之类的东西,它会自动使用长轮询作为后备。

http://dojotoolkit.org/api/1.10/dojox/socket.html

https://www.sitepen.com/blog/2012/11/05/dojo-websocket-with-amd/

Hotmail 使用网络套接字。 Web 套接字请求与 http 请求的不同之处在于,当用户访问网站时,Web 套接字连接始终保持不变。因此,通信很快就变成了这样:用户第一次打开您的网站时,他向您的服务器发送了 http 请求。由于http协议在OSI Model的第7层,请求通过TCP层与服务器建立socket连接(在OSI模型的第5层)。使用适当的服务器端网络套接字技术,服务器可以使用这种与客户端的持久套接字连接在需要时推送数据。

根据您在后端使用的语言,您可以使用几种不同的 technologies/libraries 来实现网络套接字。对于 asp.net 网络应用程序,您可以使用 Microsoft's SignalR. If you use javscript (Node.js) for your back-end than you can use Socket.io。请注意,即使您的后端没有使用 node.js,您也可以使用 Socket.io,但实现不会那么简单,因为您现在有 2 个不同的服务器,可能需要共享数据(例如:会话或数​​据库)。

Node.js 和 SignalR 的好处在于它们的性能非常好,并且对许多用户来说非常可扩展,尤其是 Node.js。这两种技术的另一个重要特性是,如果客户端的浏览器不支持 Web 套接字,它们有适当的后备方法,如服务器发送事件、Ajax 轮询、Ajax 长轮询、隐藏 iframe 元素...... .

为了进一步阅读,我推荐这个 Whosebug question