Websockets是如何实现的?

Posted

技术标签:

【中文标题】Websockets是如何实现的?【英文标题】:How Websockets are implemented? 【发布时间】:2016-04-16 06:45:11 【问题描述】: Websockets 是如何实现的? 这项新技术背后的算法是什么(与长轮询相比)? 在性能方面它们如何比长轮询更好?

我问这些问题是因为here we have a sample code of Jetty websocket implementation (server-side)。

如果我们等待的时间足够长,就会发生超时,从而导致 客户端上的以下消息。

这绝对是我在使用长轮询时面临的问题。它会停止进程以防止服务器过载,不是吗?

【问题讨论】:

请解释一下您的问题与主题的关系如何?您没有给出任何实际问题 - 如果您知道 websockets 是如何实现的,那么这将为您解决什么问题?问better ... in terms of performance 也会使问题过于宽泛。 请注意我刚刚更新了我的问题。 【参考方案1】:

关于网络套接字、长轮询和其他方法的很好的解释:

In what situations would AJAX long/short polling be preferred over html5 WebSockets?

长轮询 - 请求 → 等待 → 响应。像 AJAX 一样创建到服务器的连接,但是保持连接打开一段时间(虽然不长),在连接期间,客户端可以从服务器接收数据。由于超时或数据 eof 连接关闭后,客户端必须定期重新连接。在服务器端,它仍然被视为与 AJAX 相同的 HTTP 请求,除了请求的答案将在现在或将来的某个时间发生,由应用程序逻辑定义。支持所有主流浏览器。

WebSockets - 客户端 ↔ 服务器。创建到服务器的 TCP 连接,并根据需要保持它。服务器或客户端可以轻松关闭它。客户端经过 HTTP 兼容的握手过程,如果成功,则服务器和客户端可以随时双向交换数据。如果应用程序需要以两种方式进行频繁的数据交换,这是非常有效的。 WebSockets 确实具有数据框架,包括对从客户端发送到服务器的每条消息进行屏蔽,因此数据被简单地加密。支持图表(非常好)

总体而言,套接字比长轮询具有更好的性能,您应该使用它们而不是长轮询。

【讨论】:

是的,我之前已经看过这篇文章了。但它并没有真正回答我的问题。我想要的是对此的解释:Websockets 在 C/S 之间保持开放连接的事实与 Long Polling wait 进程并不完全相同?换句话说,为什么 Websockets 不会使服务器过载? @David - WebSocket 服务器在构建时考虑到大量持久连接,而(传统)HTTP 服务器则旨在快速处理请求。【参考方案2】:

Websockets 是如何实现的?

webSockets 实现如下:

    客户端向服务器发出 HTTP 请求,请求中带有“升级”标头 如果服务器同意升级,则客户端和服务器交换一些安全凭证,现有 TCP 套接字上的协议从 HTTP 切换到 webSocket。 现在有一个持久的开放 TCP 套接字连接客户端和服务器。 任何一方都可以随时在此打开的套接字上发送数据。 所有数据都必须以非常特定的 webSocket 数据包格式发送。

因为只要双方同意,套接字就会保持打开状态,这为服务器提供了一个通道,可以在有新内容要发送时向客户端“推送”信息。这通常比使用客户端驱动的 Ajax 调用更有效,因为客户端必须定期轮询新信息。而且,如果客户端需要向服务器发送大量消息(可能类似于多人游戏),那么使用已经打开的套接字向服务器发送快速消息也比 Ajax 调用更有效。

由于 webSockets 的启动方式(从 HTTP 请求开始,然后重新利用该套接字),它们与现有的 Web 基础设施 100% 兼容,甚至可以在与现有 Web 请求相同的端口上运行(例如端口 80 或443)。这使得跨域安全性更简单,并使客户端或服务器端基础架构上的任何人都不必修改任何基础架构来支持 webSocket 连接。

这项新技术背后的算法是什么(与 长轮询)?

本文对 webSocket 连接算法和 webSocket 数据格式的工作原理进行了很好的总结:Writing WebSocket Servers。

在性能方面它们如何比长轮询更好?

就其本质而言,长轮询有点像 hack。之所以发明它,是因为对于发送到客户端的服务器发起的数据没有更好的替代方案。步骤如下:

    客户端向客户端发出新数据的 http 请求。 如果服务器有一些新数据,它会立即返回该数据,然后客户端发出另一个 http 请求,请求更多数据。如果服务器没有新数据,那么它只是挂在连接上一段时间而不提供响应,使请求处于未决状态(套接字打开,客户端正在等待响应)。 如果在请求仍处于挂起状态的任何时候,服务器获取了一些数据,则它将该数据形成响应并返回对挂起请求的响应。 如果有一段时间没有数据进来,那么最终请求将超时。此时,客户端将意识到没有返回新数据,它将开始新的请求。 冲洗,起泡,重复。返回的每条数据或挂起请求的每次超时之后都会有来自客户端的另一个 ajax 请求。

因此,虽然 webSocket 使用一个长寿命的套接字,客户端或服务器都可以通过该套接字向另一个套接字发送数据,但长轮询包括客户端询问服务器“你还有更多数据给我吗?”一遍又一遍,每次都有一个新的 http 请求。

如果做得好,长时间轮询工作,它只是在服务器基础设施、带宽使用、移动电池寿命等方面效率不高......

我想要的是对此的解释:Websockets 保持 C/S 之间的开放连接与长轮询等待不太一样 过程?换句话说,为什么 Websockets 不会使服务器过载?

在客户端和服务器之间维护一个开放的 webSocket 连接对于服务器来说是一件非常便宜的事情(它只是一个 TCP 套接字)。一个不活动但打开的 TCP 套接字不占用服务器 CPU,只占用非常少量的内存来跟踪套接字。正确配置的服务器一次可以容纳数十万个打开的套接字。

另一方面,进行长轮询的客户端,即使是没有新信息发送给它的客户端,也必须定期重新建立其连接。每次重新建立一个新连接时,都会有一个 TCP 套接字拆除和新连接,然后是一个传入的 HTTP 请求要处理。

以下是关于缩放主题的一些有用参考:

600k concurrent websocket connections on AWS using Node.js Node.js w/1M concurrent connections! HTML5 WebSocket: A Quantum Leap in Scalability for the Web Do HTML WebSockets maintain an open connection for each client? Does this scale?

【讨论】:

谢谢。你答案的最后一部分是我正在寻找的。但是你能详细说明一下外部来源吗? @David - 为我的回答添加了一些参考。 所以,如果我理解您的回答,对客户端性能没有影响,例如对移动电池的影响?

以上是关于Websockets是如何实现的?的主要内容,如果未能解决你的问题,请参考以下文章

LAMP 专家如何轻松实现 WebSockets?

Websockets 如何区分正在发送的数据

如何使用 websockets 通过 Flask 向特定用户发送消息?

带有 C# 实现的 ASP.NET HTML5 WebSockets

Django、websockets、Tornado,如何让它们通信?

如何将 WebSockets 合并到 Cocoa 应用程序中[关闭]