WebSocket介绍

WebSocket

HTML5开始提供的一种浏览器与服务器进行全双工通讯的网络技术,属于应用层协议。它基于TCP传输协议,并复用HTTP的握手通道。

简单来说,WebSocket就是一种实现双向通信的长连接方案,双方可以随时互发消息,常用于聊天、协同编辑等场景。除了WebSocket,常用的长连接方案还有一下几种:

  1. Server-Sent Events (SSE): 客户端通过HTTP请求与服务器建立连接,可以主动向客户端推送消息。适合单向通讯场景

  2. 短轮询(Short Polling): 原理非常简单,客户端每隔几秒发一个请求,询问服务器是否有新消息。

  3. 长轮询(Long Polling,comet): 和短轮询差不多,但在返回前会阻塞客户端向服务器发送一个HTTP请求,服务器一直保持连接处于挂起状态。

  4. iframe流:利用iframe的长连接特性,从服务器实时获取数据并推送到客户端页面。同样适用于实时推送场景,维护难度大

可以看出这几种方案都是客户端主动发起连接,服务器在这里是完全被动的。不管是长轮询还是短轮询其实都非常耗费资源,需要服务器有足够的处理能力和足够高的并发。而且HTTP是非状态性的,除了真正的数据部分外,服务器和客户端还要大量交换 HTTP header,会浪费非常多的性能和流量。

而Websocket只需要建立一次连接,它是持久的,服务端会一直持有你的信息,直到交互完成连接关闭,实现了真正的长连接。

HTTP的另一个主要缺点是它是半双工的。半双工通信的特点是在同一时刻数据只能单向流动,客户端的请求流向服务器,服务器的响应流向客户端,始终是一来一回的过程。WebSocket是全双工的,客户端和服务器的数据可以同时双向流动,彻底解决了服务器的被动问题。

作用

WebSocket的优点:支持双向通信,更灵活,更高效,可扩展性更好。

WebSocket的主要问题是容易断线,如果一段时间不发数据,很可能会失效。所以一定要在代码里处理好重连的问题防止翻车,一般会用心跳( Ping/Pong)保活来维持中间网络的连接状态。至于浏览器兼容问题,现在基本可以忽略不计了,IE11也可以支持WebSocket。

应用

全量API网址:WebSocket - Web APIs | MDN

一般也不会直接用API,只需了解几个主要事件

readyState

readyState属性返回实例对象的当前状态,共有四种:

  • CONNECTING:值为0,表示正在连接。

  • OPEN:值为1,表示连接成功,可以通信了。

  • CLOSING:值为2,表示连接正在关闭。

  • CLOSED:值为3,表示连接已经关闭,或者打开连接失败。

onopen

连接成功后的回调函数

onclose

关闭成功后的回调函数

onmessage

收到服务器推送后的回调函数

send

向服务器推送

onerror

出现错误时的回调函数

socket.io

超好用的库,官方网址:Socket.IO

socketIO支持 WebSocket 协议,但要注意的是它**不是真正的WebSocket 实现,WebSocket 客户端无法连接SocketIO 服务器, SocketIO 客户端也无法连接普通 WebSocket 服务器!**双方都需要使用SocketIO 。

另外,SocketIO默认支持两种连接方式,优先使用polling,如果想使用websocket需要指定transports参数。

// 以下格式无法连接,默认使用polling连接
const socket = io("ws://echo.websocket.org");
// 指定websocket的连接方式
var socket = io('ws://localhost:4000', {transports: ['websocket']}); // 只用websocket
var socket = io("ws://localhost:4000", {
  transports: ["websocket", "polling"] // websocket优先
});

socketIO的特点

  • 自动回退:如果无法建立 WebSocket 连接,连接将回退到 HTTP 长轮询。

  • 自动重连:内含心跳保活,定期检查连接状态,意外中断时自动发起重连

  • 自动缓冲:当连接中断时,所有事件都会被延迟直到重连(不过可能会导致重连时发生大量事件,socketIO提供volatile解决这个问题)

  • 多路复用:允许通过命名空间区分拆分应用程序的逻辑

事件

发送(emit)和监听(on)

SocketIO模仿Node.js的EventEmitter,将发送事件称为emit。emit的第一个参数指定事件名称,其余参数指定事件参数,接收端通过on监听事件。它支持大部分数据类型,自动进行JSON.stringify()转换。只有部分类型需要手动序列化,具体参考发送事件 | Socket.IO

emit还可以传递回调函数,在SocketIO称为确认。只需将回调函数作为emit的参数传递即可。

// 服务器
socket.emit("update item", "1", { name: "updated" }, (response) => {});
// 客户端
socket.on("update item", (arg1, arg2, callback) 

可以为emit指定超时时间,如socket.timeout(5000).emit。对于不想缓冲到重连成功时推送,而是仅在服务器连接时发送的数据(比如实时上报位置等),使用socket.volatile.emit

广播(broadcast)和房间(room)

一般的emit是同时推送给所有客户端,broadcast可以推送给除了发送端的其余客户端。

socket.broadcast.emit("hello", "world");

Room 是一个服务器端概念,允许将数据广播到客户端的子集。

总结

基于 HTTP 的技术往往在服务器上占用更多资源,而 WebSocket 在服务器上的占用空间非常小。在实时、持续通信的场景,WebSocket 是更好的选择。

总的来说,WebSocket 和HTTP的选择依赖于业务需要的更新频率,如果需要以秒为单位更新,WebSocket更好。如果更新频率延长到半小时,则建议用短轮询。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值