一、什么是Websocket

根据 RFC 6455 标准,Websocket协议提供了一种标准化的方式在客户端和服务端之间通过TCP连接建立全双工、双向通信渠道。它是一种不同于HTTP的TCP协议,但是被设计为在HTTP基础上运行。

Websocket交互始于HTTP请求,该请求会通过HTTP Upgrade请求头去升级请求,进而切换到Websocket协议。请求报文如下:

GET /spring-websocket-portfolio/portfolio HTTP/1.1
Host: localhost:8080
Upgrade: websocket 
Connection: Upgrade 
Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==
Sec-WebSocket-Protocol: v10.stomp, v11.stomp
Sec-WebSocket-Version: 13
Origin: http://localhost:8080

我们可以看到在该请求报文中有两个特殊的请求头,一个是Upgrade请求头,代表升级为websocket协议。还有一个是Connection请求头,代表升级连接。

正常的HTTP响应报文如果正常返回,响应码是200,请求升级为websocket协议的响应报文如下:

HTTP/1.1 101 Switching Protocols 
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=
Sec-WebSocket-Protocol: v10.stomp

我们可以看到该响应报文中状态行返回的响应码是101,后面还附带了Switching Protocols切换协议关键字。

在成功握手后,底层HTTP升级请求TCP套接字会在客户端和服务端之间保持开放,从而继续发送和接收消息。


二、WebSocket部分header介绍

我们可以看到请求和响应报文中有一些特殊的websocket头部信息,这里简单的介绍一下:

  • Sec-WebSocket-Key:用于客户端与服务端初次握手唯一标识,Base64编码字符串。
  • Sec-WebSocket-Accept:初次握手服务端返回的唯一标识,也是Base64编码字符串,用来证明来自客户端的握手请求已经收到了,该响应头的值为:SHA-1(“Sec-WebSocket-Key” + “GUID”),然后再经过Base64编码。
  • Sec-WebSocket-Protocol:WebSocket子协议,比如可以是STOMP协议。
  • Sec-WebSocket-Version:WebSocket协议版本号,值必须为13。

三、HTTP VS WebSocket

虽然WebSocket被设计成和HTTP协议兼容,但是两种协议有不同的架构和应用编程模型。

在HTTP和REST中,应用被模型化为许多URL,客户端和应用交互需要访问这些URL,服务端对请求进行路由并交给合适的处理器,处理器会基于HTTP URL、方法和头部进行处理。

WebSocket和HTTP相反,通常只有一个URL用于初始链接,后面所有应用消息都会在相同的TCP连接上传输,这是一种完全不同的异步、事件驱动的消息。

WebSocket也是一种低级的传输协议,不像HTTP,它并没有规定消息内容的语义,也就意味着客户端和服务端之间如果没有对消息语义达成一致,是没办法路由和处理消息的。

WebSocket客户端和服务端之间可以协商使用更高级消息协议,比如STOMP,可以通过HTTP握手请求的请求头Sec-WebSocket-Protocol指定。


四、什么时候使用WebSockets

WebSockets可以让Web页面动态化和可交互,然而,在很多场景下,AJAXHTTP Streaming或者长轮询也能提供简单、有效的解决方案。

例如,新闻、邮件和社会实事需要动态更新,每几分钟更新一次就好。而协作类、游戏和金融类APP需要更加的实时。

延时也不是决定性因素,如果消息体量比较小,HTTP Streaming或者长轮询也能解决,而像低延时、高频次和大消息体量的场景,WebSocket更适合。


五、关于SockJS和STOMP

SockJSSTOMP 都是用于 Web 应用程序与消息代理进行通信的技术,但它们解决的问题不同。

SockJS 是一个 JavaScript 库,它提供了一种在 Web 浏览器和 Web 服务器之间建立 WebSocket 连接的跨浏览器解决方案。

SockJS 旨在解决 WebSocket 不受支持或无法使用的情况下,使用轮询和其他技术建立实时双向通信的问题。SockJS 库支持多种传输方式,包括 WebSocket、XHR 流、XHR 短轮询等,从而保证了最大的兼容性和可靠性。

STOMP(Simple Text Oriented Messaging Protocol)是一种基于文本的简单消息协议,它提供了一种可互操作性的机制,用于跨语言和平台之间的实时消息传递。

STOMP 协议定义了一组命令和消息格式,用于在客户端和服务器之间进行消息传递,它与特定的消息代理无关,因此可以使用 STOMP 协议与多个消息代理进行通信。STOMP 支持订阅/发布模式和点对点模式,可以用于实现诸如聊天室、通知系统和实时数据更新等应用程序。

通常情况下,使用 SockJSSTOMP结合使用可以获得最佳的性能和可靠性。

SockJS 提供了一种建立 WebSocket 连接的可靠跨浏览器解决方案,而 STOMP 提供了一种在 WebSocket 连接上实现实时消息传递的标准化协议。

在使用 SockJSSTOMP 的组合时,可以使用 SockJS 建立 WebSocket 连接,然后使用 STOMP 协议在 WebSocket 连接上进行消息传递,从而获得最佳的性能和可靠性。

WebSocket的那些事(1-概念篇)-LMLPHP

05-02 21:24