WebSocket:实现实时互动、数据推送的利器,你了解多少

WebSocket技术是一种基于TCP协议的全双工通信协议,它允许浏览器和服务器之间进行实时、双向的通信。相比传统的HTTP请求-响应模式,WebSocket提供了持久连接,可以实时地推送数据,减少了通信的延迟。

WebSocket的工作原理是通过建立一条持久连接来实现实时通信。首先,浏览器和服务器进行一次标准的HTTP握手,建立连接。随后,连接升级为WebSocket协议,之后就可以在连接上发送和接收消息,实现双向通信。

WebSocket的应用非常广泛。以下是几个典型的应用场景:

即时通讯:WebSocket可用于实现聊天应用、在线客服系统等,用户可以实时地发送和接收消息。

实时数据展示:通过WebSocket可以实时地推送数据给前端,比如实时股票行情、实时天气更新等。

多人游戏:WebSocket可以实现多人在线游戏,玩家可以实时地进行交互、通信。

实时协作:比如实时协同编辑器,多个用户可以同时编辑一个文档,并实时地看到其他用户的操作。

数据监控:WebSocket可以用于实时监控系统的运行状态、日志更新等,便于及时发现和解决问题。

使用WebSocket技术也需要考虑一些方面:

浏览器和服务器的兼容性:不是所有浏览器都完全支持WebSocket,需要进行兼容性测试和处理,可能需要对不支持的浏览器使用其他技术(如轮询或长轮询)来进行实时通信。

负载均衡和扩展性:如果应用需要处理大量的并发连接,需要考虑负载均衡和扩展性,可以使用多个WebSocket服务器配合负载均衡器来实现。

总结起来,WebSocket技术提供了一种实时、双向通信的方式,适用于各种需要实时交互和实时数据推送的应用场景。它使得Web应用能够更加实时、高效地进行通信,提供了更好的用户体验。

虽然WebSocket只需要建立一次就可以让客户端和服务端建立起连接,但是因为是基于TCP协议构建的,所以本质上还是要进行三次握手。

TCP本身是持久连接,三次握手和四次挥手就不老调重弹了。而HTTP之所以是单向的,是因为规范规定了服务器只能响应请求,而不能主动发送数据。所以说WebSocket可以看做是HTTP的一个补丁

协议概览

WebSocket协议在游览器中的显示是这样的:

1942b58ae280ba6c58a73722971faef5.jpeg

我们可以看到不同于一般的请求,WebSocket URL前缀为ws,它告诉游览器自己不是HTTP请求,而是WebSocket请求,此时游览器便会自动对协议进行升级。

默认ws端口是80,wss端口是443。

wss就是通过TLS加密后的ws。

不同于一般的HTTP请求,WebSocket请求添加了几个字段来作为应用,主要的有:

Sec-WebSocket-Accept和Sec-WebSocket-Key:只有当Sec-WebSocket-Key的值经过固定算法加密后的数据和响应头里的Sec-WebSocket-Accept的值保持一致,该连接才会被认可建立,避免跨协议攻击。 Sec-WebSocket-Version:这个header字段的值必须为13,因为在它之前有很多测试的版本,比如9、10、11、12,这些版本现在都不被认为是有效的Sec-WebSocket-Version。 Sec-WebSocket-Extensions:该属性存储客户端的扩展,在连接建立时服务端可以针对该扩展进行处理。 Upgrade:告诉游览器该HTTP协议已经升级到了WebSocket。

当客户端对服务端发起WebSocket请求时,只有在当前连接已经建立的情况下才能再次建立连接(客户端会对剩下的连接进行排序)。因为WebSocket是长连接,所以客户端需要注意限制同一个主机的连接数量,避免脚本通过创建大量的WebSocket连接来进行DDOS攻击。如果客户端是通过代理访问服务的,那么客户端应该连接到那个代理并且通过这个代理去和服务端建立一个TCP连接。

在服务端接收客户端的WebSocket请求后,需要对该请求进行解析,获取它的Sec-WebSocket-Key、Sec-WebSocket-Version、Sec-WebSocket-Extensions,还有客户端的源地址、请求的资源名称等。当解析完成后,如果能与服务端连接,那么服务端将会返回给客户端一个响应,响应里面包含Sec-WebSocket-Accept,这是与客户端对接的标识符。

当客户端与服务端建立好连接后,两者就可以通信了:

0e702e2a83142250fd4518fdeaff36c9.jpeg

协议结构

WebSocket协议的全局结构大概如下所示,我们来大概解析一下它各个字段的含义:

d676310ce799c5fa9a39e998fe68a15a.jpeg

FIN:表示这是消息的最后一个字段(设置为1,默认为0)。

RESV1/RESV2/RESV3:标识是否有扩展协议,如果为1,那么在EXTEND PAYLOAD为0的情况下,就会断开WebSocket连接。

OPCODE:标识操作码,这是一个操作帧,用来指示WebSocket的动作。默认的标识码有:

%x0 :一个连续的消息分片 %x1 :一个文本类型的消息分片 %x2 :一个二进制类型的消息分片 %x3-7:预留给以后的数据帧 %x8 :一个关闭连接的指令 %x9 :一个ping包 %xA :一个pong包 %xB-F:预留给以后的控制帧

ping包和pong包是用来做心跳检测的。

MASK:标识数据是否有加掩码,如果设置为1,掩码键必须放在MASKING KEY区域。

PAYED LENGTH:传输的数据的长度(不包括MASKING-KEY)。

MASKING-KEY:掩码键。

PAYLOAD DATA:传输的数据(扩展数据EXTEND PAYLOAD+应用数据APPLICATION PAYLOAD)。

扩展数据:自己定义的扩展协议。 应用数据:基础的数据帧。 前端处理

HTML5封装好了处理方法,只需要调用其API就可以了。

直接创建一个WebSocket对象,然后将onopen\onclose等方法绑定到对象。

相关API可以查看MDN WEB——API WebSocket。

后端处理

用Netty的WebSocketServerProtocolHandler举例,当我们创建WebSocket服务时,必然要加入一个WebSocket协议的处理器,将其协议内容封装为一个便于使用的包装类,在Netty中,我们可以这样定制WebSocket服务:

23c4d6f7a2bda8848944a720442dbbf0.jpeg

进入WebSocketServerProtocolHandler类,可以看到它定义的属性有:

ad28314002e97446f430f971d2d860df.jpeg它两个方法有:

一个是handlerAdded,它会在Channel连接后回调,每次都会插入WebSocketServerProtocolHandshakeHandler。

774f84f2c85c86182da2742a12162cb2.jpeg

一个是decode,它会针对进行的数据帧进行操作。

621a3805861d2d187e1775cc023ed514.jpeg

在close前要进行frame.retain();,是因为在关闭时需要用到frame,在Netty的所有操作都是异步的情况下,这样就可以防止frame在没有用完时就被释放掉了。

来看下WebSocketServerProtocolHandshakeHandler.channelRead方法:

b8c79a41e04aa05a9835943e83031032.jpeg

在WebSocketServerProtocolHandshakeHandler.channelRead绑定触发事件时,为了保持兼容性,所以设置了两个,第一个是过时的,下面那个是新的。

对于通过握手器工厂WebSocketServerHandshakerFactory创建的WebSocketServerHandshaker,我们需要注意它的handshake方法。该方法其实就是来发送响应数据的。

它先把跟HTTP聚合,压缩的处理器移除,然后看有没有HttpRequestDecoder,如果没有,那就在前面添加WebSocket的编解码器。如果有HTTP编解码器,就把编解码器替换成WebSocket编解码器,等发送响应成功了,就移除掉HttpServerCodec或HttpResponseEncoder。

e1a2e32617401ee5810a27e3f1357ef8.jpeg

这样处理完之后,就把和HTTP编解码器移除出去了,这样的话就可以保证使用者即使添加了错误的处理器,程序也可以正常执行WebSocket连接。

总结

WebSocket协议用于长连接传输数据,本质也不过是定义了一种协议格式,然后往里面放数据。从功能上来说唯一和HTTP的区别就是客户端和服务端是可以相互推送消息的,而非被动。

之前说过HTTP 1.1添加了一个keep-alive请求头属性,可以作用于长连接。但是这里的长连接和WebSocket的长连接不同。keep-alive的作用是保持连接,可以让其它的HTTP请求可以复用这个通道,每次HTTP请求还是要携带请求头的。而WebSocket的长连接的每一个连接对应一个客户端。

一个很明显的比方就是打电话给客服。keep-alive的表示是一方讲完之后就把电话给了自己身后的人,然后身后的人跟客服反映新的问题。WebSocket表示一方讲完之后,听完客服的反馈就挂掉了电话,两人就断了联系。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WebSocket 和 RabbitMQ 可以结合使用来实现实时消息推送WebSocket 是一种基于 TCP 的协议,它允许在客户端和服务器之间建立持久的双向通信通道。而 RabbitMQ 是一个消息代理和队列管理系统,可以实现消息的可靠传输和分发。 下面是使用 WebSocket 和 RabbitMQ 实现实时消息推送的一般步骤: 1. 配置 WebSocket 服务器:在后端应用程序中,你需要配置一个 WebSocket 服务器,用于接收和处理客户端的 WebSocket 连接请求。可以使用 Spring Boot 中的 Spring WebSocket 或其他 WebSocket 框架进行配置。 2. 配置 RabbitMQ:在后端应用程序中,你需要配置 RabbitMQ 的连接信息,并创建一个或多个交换机和队列。可以使用 RabbitMQ 的 Java 客户端库进行配置。 3. 监听 RabbitMQ 消息:在后端应用程序中,你需要监听 RabbitMQ 中指定队列的消息。当有新的消息到达时,通过 WebSocket 服务器将消息推送给客户端。 4. 前端连接 WebSocket:在前端应用程序中,你需要使用 JavaScript 的 WebSocket API 连接到后端WebSocket 服务器。 5. 接收消息并更新 UI:在前端应用程序中,当接收到 WebSocket 服务器推送的消息时,你可以在界面上实时展示或处理这些消息。 通过结合使用 WebSocket 和 RabbitMQ,你可以实现实时、双向的消息通信,并将消息推送给多个客户端。这种方式适用于需要实时更新消息的应用场景,如聊天应用、实时监控等。需要根据具体的技术栈和需求进行相应的配置和开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值