WebSocket

一、WebSocket是什么

WebSocket,是一种网络传输协议,位于 OSI 模型的应用层。可在单个 TCP 连接上进行全双工通信,能更好的节省服务器资源和带宽并达到实时通迅 客户端和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输

WebSocket_第1张图片

二、特点

全双工 通信允许数据在两个方向上同时传输,它在能力上相当于两个单工通信方式的结合 例如指 A→B 的同时 B→A ,是瞬时同步的 二进制帧 采用了二进制帧结构,语法、语义与 HTTP 完全不兼容,相比 http/2,WebSocket 更侧重于“实时通信”,而 HTTP/2 更侧重于提高传输效率,所以两者的帧结构也有很大的区别 不像 HTTP/2 那样定义流,也就不存在多路复用、优先级等特性 自身就是全双工,也不需要服务器推送 协议名 引入 ws 和 wss 分别代表明文和密文的 websocket 协议,且默认端口使用 80 或 443,几乎与 http 一致


    
    
      
      
      
      
  1. ws: //www.chrono.com
  2. ws: //www.chrono.com:8080/srv
  3. ws: //www.chrono.com:445/im?user=user_id=xxxx

握手 WebSocket 也要有一个握手过程,然后才能正式收发数据 客户端发送数据格式如下:

GET /chat HTTP/1.1  Host: server.example.com Upgrade: websocket Connection:  Upgrade  Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==  Origin: http://example.com Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version:  13
    
    
      
      
      
      
  • Connection:必须设置 Upgrade,表示客户端希望连接升级

  • Upgrade:必须设置 Websocket,表示希望升级到 Websocket 协议

  • Sec-WebSocket-Key:客户端发送的一个 base64 编码的密文,用于简单的认证秘钥。要求服务端必须返回一个对应加密的“Sec-WebSocket-Accept 应答,否则客户端会抛出错误,并关闭连接

  • Sec-WebSocket-Version :表示支持的 Websocket 版本

服务端返回的数据格式: 


    
    
      
      
      
      
  1. HTTP/1.1 101 Switching Protocols
  2. Upgrade: websocket
  3. Connection: Upgrade
  4. Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=Sec-WebSocket-Protocol: chat

HTTP/1.1 101 Switching Protocols:表示服务端接受 WebSocket 协议的客户端连接

  • Sec-WebSocket-Accep:验证客户端请求报文,同样也是为了防止误连接。具体做法是把请求头里“Sec-WebSocket-Key”的值,加上一个专用的 UUID,再计算摘要

优点

  • 较少的控制开销:数据包头部协议较小,不同于 http 每次请求需要携带完整的头部

  • 更强的实时性:相对于 HTTP 请求需要等待客户端发起请求服务端才能响应,延迟明显更少

  • 保持创连接状态:创建通信后,可省略状态信息,不同于 HTTP 每次请求需要携带身份验证

  • 更好的二进制支持:定义了二进制帧,更好处理二进制内容

  • 支持扩展:用户可以扩展 websocket 协议、实现部分自定义的子协议

  • 更好的压缩效果:Websocket 在适当的扩展支持下,可以沿用之前内容的上下文,在传递类似的数据时,可以显著地提高压缩率

HTTP 协议的“缺陷”

了解http的人都知道,HTTP 协议有一个缺陷:通信只能由客户端发起。例如,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息的, 这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦,客户端只能使用”轮询”的方式,即每隔一段时间,就发出一个请求,请求服务器有没有状态变化 。可见轮询的效率低,非常浪费资源。

在http1.1中,默认开启了一个叫Keep-alive的参数,官方的说法是可以用这个来作为长连接。你是否以为既然客户端与服务器保持了长连接,服务器就能主动给客户端推送消息呢?

关于Keep-alive的缺点

Keep-alive的确可以实现长连接,但是这个长连接是有问题的,本质上依然是客户端主动发起-服务端应答的模式,是没法做到服务端主动发送通知给客户端的。也就是说,在一个HTTP连接中,客户端可以发送多个Request,接收多个Response。但是请记住 Request = Response , 在HTTP中永远是这样,一个request只能有一个response。而且这个response也是被动的,不能主动发起。放上一张图,图左为没开启Keep-alive,图右为开启了Keep-alive,可以看出依然是一问一答的模式,向较左边只是省略了每次的关闭和打开操作。

WebSocket_第2张图片

需要注意的是Keep-alive是指不需要多次建立连接,而非http2.0里面的多路复用,多路复用的意思是客户端可以同时向服务器端发送多个请求,服务器端也可以同时响应多个Response.

WebSocket_第3张图片

关于websocket

那么如果我们需要服务器状态变化的时候能够主动通知客户端,我们有没有什么办法呢?这就要用到websocket。

WebSocket_第4张图片

上图对比可以看出,相对于传统 HTTP每次请求-应答都需要客户端与服务端建立连接的模式,WebSocket是类似 Socket 的 TCP 长连接的通讯模式,一旦 WebSocket 连接建立后,后续数据都以帧序列的形式传输。在客户端断开 WebSocket 连接或 Server 端断掉连接前,不需要客户端和服务端重新发起连接请求。在海量并发及客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息是在同一个持久连接上发起,实时性优势明显。

WebSocket API 是 HTML5 标准的一部分, 但这并不代表 WebSocket 一定要用在 HTML 中,或者只能在基于浏览器的应用程序中使用。

在WebSocket中,只需要服务器和浏览器通过TCP协议进行一个握手的动作,然后单独建立一条TCP的通信通道进行数据的传送。WebSocket同HTTP一样也是应用层的协议,但是它是一种双向通信协议,是建立在TCP之上的。websocket的流程大概是以下几步:

1、浏览器、服务器建立TCP连接,三次握手。这是通信的基础,传输控制层,若失败后续都不执行。2、TCP连接成功后,浏览器通过HTTP协议向服务器传送WebSocket支持的版本号等信息。(开始前的HTTP握手) 3、服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据。4、当收到了连接成功的消息后,通过TCP通道进行传输通信。

也就是说WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要TCP协议的。

看看一次websocket的握手请求与应答的报文

WebSocket 客户端连接报文

GET /webfin/websocket/ HTTP/1.1  Host: localhost Upgrade: websocket Connection:  Upgrade  Sec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==  Origin: http://localhost :8080  Sec-WebSocket-Version:  13
    
    
      
      
      
      

可以看到,客户端发起的 WebSocket 连接报文类似传统 HTTP 报文,”Upgrade:websocket”参数值表明这是 WebSocket 类型请求,“Sec-WebSocket-Key”是 WebSocket 客户端发送的一个 base64 编码的密文,要求服务端必须返回一个对应加密的“Sec-WebSocket-Accept”应答,否则客户端会抛出“Error during WebSocket handshake”错误,并关闭连接。

服务端收到报文后返回的数据格式类似:

WebSocket 服务端响应报文


    
    
      
      
      
      
  1. GET /webfin/websocket/ HTTP/1.1
  2. Host: localhost
  3. Upgrade: websocket
  4. Connection: Upgrade
  5. Sec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==
  6. Origin:
  7. http://localhost
  8. :8080
  9. Sec-WebSocket-Version: 13

“Sec-WebSocket-Accept”的值是服务端采用与客户端一致的密钥计算出来后返回客户端的,“HTTP/1.1 101 Switching Protocols”表示服务端接受 WebSocket 协议的客户端连接,经过这样的请求-响应处理后,客户端服务端的 WebSocket 连接握手成功, 后续就可以进行 TCP 通讯了。

WebSocket与Socket的关系

Socket其实并不是一个协议,而是为了方便使用TCP或UDP而抽象出来的一层,是位于应用层和传输控制层之间的一组接口。

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

当两台主机通信时,必须通过Socket连接,Socket则利用TCP/IP协议建立TCP连接。TCP连接则更依靠于底层的IP协议,IP协议的连接则依赖于链路层等更低层次。

WebSocket则是一个典型的应用层协议。

WebSocket 与 HTTP

WebSocket 协议在2008年诞生,2011年成为国际标准。现在所有浏览器都已经支持了。WebSocket 的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话。

HTTP 有 1.1 和 1.0 之说,也就是所谓的 keep-alive ,把多个 HTTP 请求合并为一个,但是 Websocket 其实是一个新协议,跟 HTTP 协议基本没有关系,只是为了兼容现有浏览器,所以在握手阶段使用了 HTTP 。

下面一张图说明了 HTTP 与 WebSocket 的主要区别:

WebSocket_第5张图片

WebSocket 的其他特点:

  • 建立在 TCP 协议之上,服务器端的实现比较容易。

  • 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

  • 数据格式比较轻量,性能开销小,通信高效。

  • 可以发送文本,也可以发送二进制数据。

  • 没有同源限制,客户端可以与任意服务器通信。

  • 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

WebSocket原理及如何实现长连接

websocket相当于HTTP的一个补充协议,通过http request建立连接,不需要再发送request,之后保持一端与另外一端的TCP连接。

在实际应用中,一个socket与另外一端的连接可能会经过千山万水(多个路由、多个中间服务器),中间有各种转发、过滤。

所以后来更新了,添加了Ping/Pong Frame(RFC 6455 - The WebSocket Protocol),可以说这是一个特殊的数据包,

这个数据包只有简单的一些的元数据,不涉及数据传输。维持连接的活跃性与持久性。

参考文献

  • httpss://zh.wikipedia.org/wiki/WebSocket

  • httpss://www.oschina.net/translate/9-killer-uses-for-websockets

  • httpss://vue3js.cn/interview

  • httpss://www.cnblogs.com/Javi/p/9303020.html

  • httpss//blog.csdn.net/qq_35447305/article/details/52966105

你可能感兴趣的:(网络编程,websocket,网络协议,网络)