你是否好奇在线聊天、股票行情推送或多人游戏如何做到信息瞬间传递?背后的关键正是WebSocket技术。
在WebSocket出现之前,网页应用主要依赖HTTP协议。但HTTP有一个明显的缺点:它遵循“一问一答”的模式。浏览器发出请求,服务器返回响应,然后连接就断开了。这对于加载网页、提交表单没问题,但对于需要实时获取更新的应用,就显得力不从心。
想象一下网页版聊天室。如果只用HTTP,有两种方法:
不断刷新(轮询):浏览器每隔几秒就问服务器:“有新消息吗?”大部分时间可能没有新消息,造成网络和服务器资源的浪费。
长轮询:浏览器问“有新消息吗?”,服务器一直不回答,直到真的有新消息或者等待超时。这样能减少无效请求,但每次收到消息或超时后,都要重新建立连接,依然有延迟和开销。
通信方式 | 典型场景 | 特点 | 实时性 |
---|---|---|---|
HTTP请求 | 加载网页、提交表单 | 客户端发起请求,服务器响应后断开连接 | 低 |
WebSocket | 聊天室、实时游戏、协作编辑 | 建立长连接,支持双向实时数据流 | 高 |
简单说,WebSocket是一种网络通信协议。它让浏览器(或任何客户端)和服务器之间建立一条持久的、双向的通信通道。这条通道一旦建立成功,双方可以随时、主动地向对方发送数据,无需等待请求,就像接通的电话线一样。这就是它实现低延迟、实时通信的基础。
WebSocket连接始于一个特殊的HTTP请求,称为“握手”。客户端发送一个包含升级头的请求:
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket // 请求升级协议
Connection: Upgrade // 请求升级连接
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== // 客户端随机密钥
Sec-WebSocket-Version: 13 // 使用的WebSocket协议版本
服务器如果支持WebSocket,会返回一个类似这样的响应:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= // 基于客户端Key计算出的响应
这个“101 Switching Protocols”响应码表示协议切换成功。之后,连接就从普通的HTTP升级到了WebSocket协议,数据直接在底层的TCP连接上传输,格式遵循WebSocket帧规范。
真正的双向实时通信:服务器有新数据时能立即推送给客户端,客户端也能随时发送数据给服务器,无需等待。
超低延迟:连接建立后一直保持,数据直接在通道上传输,省去了反复建立连接的开销。
高效省资源:避免了HTTP轮询产生的大量无用请求头和响应头,减少了网络带宽和服务器CPU的消耗。
由于WebSocket是长连接,中间可能经过防火墙或代理服务器。这些设备有时会关闭长时间没有数据流动的连接。为了防止这种情况,需要心跳机制来“保活”。
心跳原理很简单:
客户端定期(如每25秒)向服务器发送一个很小的Ping帧。
服务器收到Ping后,必须立即回复一个Pong帧。
如果客户端连续几次(如3次)发送Ping后都没收到Pong,就认为连接已断开,需要尝试重新连接。
class WebSocketClient {
constructor(url) {
this.url = url;
this.HEARTBEAT_INTERVAL = 25000; // 25秒
this.HEARTBEAT_TIMEOUT = 3000; // 等待Pong超时3秒
this.heartbeatInterval = null;
this.heartbeatTimeout = null;
this.connect();
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.addEventListener('open', () => this.startHeartbeat());
this.ws.addEventListener('close', () => this.clearHeartbeat());
// ... 其他事件监听(message, error)
}
startHeartbeat() {
this.clearHeartbeat(); // 清除之前的定时器
// 每隔一段时间发送Ping
this.heartbeatInterval = setInterval(() => {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify({ type: 'ping' })); // 发送Ping
this.setHeartbeatTimeout(); // 设置等待Pong的超时
}
}, this.HEARTBEAT_INTERVAL);
// 连接建立后立即发送一次Ping并等待
this.ws.send(JSON.stringify({ type: 'ping' }));
this.setHeartbeatTimeout();
}
setHeartbeatTimeout() {
this.clearHeartbeatTimeout();
// 设定超时:如果这段时间内没收到Pong,认为连接断开
this.heartbeatTimeout = setTimeout(() => {
console.error('心跳超时,连接可能已断开');
this.ws.close(); // 主动关闭并触发重连逻辑
}, this.HEARTBEAT_TIMEOUT);
}
handlePong() {
this.clearHeartbeatTimeout(); // 收到Pong,清除等待超时
}
clearHeartbeat() {
clearInterval(this.heartbeatInterval);
this.clearHeartbeatTimeout();
}
clearHeartbeatTimeout() {
clearTimeout(this.heartbeatTimeout);
}
}
实际使用中,WebSocket库通常内置心跳机制,开发者只需配置间隔时间。
WebSocket是以下应用的理想选择:
即时通讯:聊天应用、在线客服系统。
实时数据推送:股票行情、体育赛事比分、新闻快讯、监控仪表盘。
多人在线协作:文档协同编辑(如腾讯文档)、在线白板。
多人在线游戏:需要玩家状态实时同步的游戏。
物联网(IoT):设备状态实时监控与控制。
安全性:务必使用wss://(基于TLS加密的WebSocket),尤其是在传输敏感信息或涉及用户登录时。
连接管理:处理好连接断开后的自动重连(可尝试指数退避策略)。
身份验证:在建立WebSocket连接时(握手阶段)进行用户身份验证(常用Token)。
消息格式:WebSocket传输的是原始字节或文本帧,通常需要约定应用层的消息格式(如JSON)。
浏览器兼容性:现代浏览器(Chrome, Firefox, Safari, Edge等)都已良好支持WebSocket。
作为实时通信的基石,WebSocket技术仍在发展。新的协议如WebTransport旨在提供更灵活的多路复用和更快的连接建立(0-RTT)。同时,成熟的库如Socket.IO、SignalR等不仅封装了WebSocket,还提供了房间管理、广播、自动重连、协议降级(在不支持WebSocket时使用轮询)等高级功能,大大简化了开发。
WebSocket通过建立持久、双向的通信通道,彻底解决了HTTP协议在实时性上的瓶颈。它带来的低延迟、高效率特性,支撑着聊天室、在线游戏、实时协作等众多现代网络应用的流畅体验。理解其工作原理和最佳实践,对于构建需要实时交互能力的应用至关重要。当你下一次享受即时消息或流畅的多人游戏时,不妨想想背后默默工作的WebSocket技术。
每个 Vue 实例都实现了事件接口vm.$emit( event, arg ) 触发当前实例上的事件;vm.$on( event, fn )监听event事件后运行。实例说明:Vuejs 用$emit与$on来进行兄弟组件之间的数据传输通信,Vuejs 用$emit与$on来进行跨页面之间的数据传输通信
两个浏览器窗口间通信:一个窗口更新localStorage,另一个窗口监听window对象的storage事件来实现通信;所有的WebSocket都监听同一个服务器地址,利用send发送消息,利用onmessage获取消息的变化;借助iframe 或 window.open;HTML5 中的 Web Worker 可以分为两种不同线程类型
在浏览器中,我们可以同时打开多个Tab页,每个Tab页可以粗略理解为一个“独立”的运行环境,即使是全局对象也不会在多个Tab间共享。然而有些时候,我们希望能在这些“独立”的Tab页面之间同步页面的数据、信息或状态。
使用Vue也有很长一段时间,但是一直以来都没对其组件之间的通信做一个总结,这次就借此总结一下。父子组件之间的通信props和$emit 父组件通过props将数据下发给props
前端开发过程中,总是避免不了要进行前端标签页之间的通信,最经典的例子莫过于音乐播放网站中,当第一次点击播放列表中的歌曲时,它会打开一个新的标签页进行播放,而当在列表中再次点击歌曲播放时
我们的项目是基于 ThinkJS + Vue 开发的,最近实现了一个多端实时同步数据的功能,所以想写一篇文章来介绍下如何在 ThinkJS 的项目中利用 WebSocket 实现多端的实时通信。ThinkJS 是基于 Koa 2 开发的企业级 Node.js 服务端框架
其实服务器的处理和客户端大同小异,分三个逻辑分支:检索成功,用检索到的Socket来处理接收报文;检索失败,服务器侦听(listen)目的端口,创建全新的Socket服务客户;检索失败,服务器没有侦听目的端口,丢弃处理
如何实现两个组件之间的双向传递呢?即,在父组件中修改了值,子组件会立即更新。在子组件中修改了值,父组件中立即更新。vue中有一个很神奇的东西叫v-model,它可以完成我们的需求。
vue项目的一大亮点就是组件化。使用组件可以极大地提高项目中代码的复用率,减少代码量。但是使用组件最大的难点就是父子组件之间的通信。父组件通过$refs调用子组件的方法。 以上就是父子组件通信的方式
在微服务架构的世界中,我们通过一系列服务构建应用。集合中的每项服务都符合以下标准:松散耦合、可维护和可测试、可以独立部署,微服务架构中的每个服务都解决了应用中的业务问题
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!