Long Polling vs WebSocket:实时通信该如何选择?

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

JavaScript中的Long Polling vs WebSocket:实时通信的巅峰对决

\n\n

曾几何时,在互联网速度缓慢、浏览器功能简单的年代,了解服务器上是否有新数据的唯一方法就是按F5刷新页面。后来AJAX出现了,我们学会了手动向服务器发送请求。但如果数据应该自动到来,无需我们主动请求呢?欢迎来到实时通信的世界。

\n\n

在本文中,我们将探讨至今仍在开发者社区中引发争论的两种主要方法:经典可靠的Long Polling和现代激进的WebSocket。我们将用JavaScript编写代码,深入了解它们的内部机制,并弄清楚在下一个项目中应该选择哪种工具。如果你想一劳永逸地搞懂long polling vs websocket,那你来对地方了。

\n\n

问题:如何让服务器先开口?

\n\n

HTTP是一种单向协议。客户端(浏览器)发送请求,服务器给出响应——然后通信就结束了。但在现实世界中(聊天、股票行情、通知),数据需要反向流动。长期以来,开发者们想方设法解决这个问题。以下是两种主要的解决方案。

\n\n

Long Polling:巧妙的时间把戏

\n\n

想象一下,你给客服打电话说:“我会在线等待,直到有客服人员空闲。”你没有挂断电话。这正是Long Polling(也称为“长轮询”)的工作原理。

\n\n

工作原理:

\n
    \n
  • 客户端发送一个普通的HTTP请求。
  • \n
  • 如果没有数据,服务器不会立即响应。它会“挂起”并等待。
  • \n
  • 一旦有数据出现,服务器就会发送响应。
  • \n
  • 客户端处理响应后,立即建立新的连接。
  • \n
\n\n

客户端代码(JavaScript):

\n
function longPoll() {\n  fetch('/updates')\n    .then(response => response.json())\n    .then(data => {\n      console.log('新数据:', data);\n      // 立即开始新的轮询\n      longPoll();\n    })\n    .catch(error => {\n      console.error('错误,2秒后重新连接:', error);\n      setTimeout(longPoll, 2000);\n    });\n}\n\n// 启动\nlongPoll();
\n\n

优点:

\n
    \n
  • 适用于任何服务器和任何浏览器(甚至IE6)。
  • \n
  • 不需要特殊协议——纯HTTP。
  • \n
  • 能穿透任何企业代理和防火墙。
  • \n
\n\n

缺点:

\n
    \n
  • 每条消息都是一个全新的HTTP请求(包含头部、Cookie等开销)。
  • \n
  • 服务器需要保持大量打开的连接(C10k问题——1万个客户端)。
  • \n
  • 延迟(latency)高于WebSocket。
  • \n
\n\n

WebSocket:永久的通信通道

\n\n

WebSocket就像宇宙飞船和地面控制中心之间的开放线路。你只需建立一次连接,之后双方可以随时发送数据,无需任何额外仪式。

\n\n

工作原理:

\n
    \n
  • 客户端通过HTTP发起握手。
  • \n
  • 服务器将协议切换为ws://或wss://。
  • \n
  • 建立永久的双向连接。
  • \n
  • 数据以帧的形式传输——轻量且快速。
  • \n
\n\n

客户端代码(JavaScript):

\n
const socket = new WebSocket('wss://example.com/chat');\n\n// 当连接打开时\nsocket.onopen = function() {\n  console.log('连接已建立');\n  socket.send(JSON.stringify({ type: 'greeting', text: '你好,服务器!' }));\n};\n\n// 当收到消息时\nsocket.onmessage = function(event) {\n  const data = JSON.parse(event.data);\n  console.log('来自服务器的消息:', data);\n};\n\n// 发生错误时\nsocket.onerror = function(error) {\n  console.error('WebSocket错误:', error);\n};\n\n// 连接关闭时\nsocket.onclose = function(event) {\n  console.log('连接已关闭。代码:', even                

博客

书籍推荐