WebSocket网络通信协议

Posted 俊king

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WebSocket网络通信协议相关的知识,希望对你有一定的参考价值。

WebSocket网络通信协议

网络部分的方向:

  1. 网络编程--->socket编程,epoll,reactor--->主要解决一个server对应多个客户端(并发)
  2. 网络协议--->tcp,http,upd,https--->主要解决一个客户端与一个server之间通信的时候传输的数据格式(协议头、协议内容、ip头、不同场景如何)

WebSocket相关内容

特点:

  1. 基于tcp的协议--->主要解决多个客户端一个服务器传输数据过程中的粘包的问题

说明:

  1. tcp协议的特点--->流式套接字(buffer,特点:我发数据对方肯定能收到,对方发数据我也能收到.先发的数据先收到)--->数据必达性,数据顺序不乱

场景举例:

客户端发送两个包(package1package2),服务端只调用了一次rec(fd, buffer, length, 0)就全部接收到了.

问题:

buffer当中包含了两个包的数据,服务端如何去区别buffer当中是两个包数据还是一个包数据

所有tcp的应用协议需要解决的问题:

  1. 如何分包(tcp只做到了数据必达以及先发先收)
  2. 发送明文还是密文(RSA非对称还是对称)

解决办法:

  1. 定义长度(length)
  2. 做一个分隔符

WebScoket核心:

  1. 解决粘包的问题--->基于tcp的应用协议解决的问题就是如何粘包
  2. 应用于业务场景的时候,因为websocket只做了如何解决粘包的处理(传输是否是明文...),所以还需要加上一层关于业务场景定义的协议(里面传的数据格式与websocket无关(比如传jsonxml什么的))

协议说明:

例如:https://www.baidu.comsw://192.168.x.x:8888

  • xxx://说明的是协议--->使用什么协议访问资源
  • www.baidu.com--->域名或者主机(去DNS上面找到对应的域名访问)
  • 在下面的/后面的内容--->访问哪个location--->访问什么资源

翻译:

采用什么协议访问哪台机器的哪个资源?

内容发送解析:

  1. request什么时候发送?--->握手handshake(这里面没有6字节的字节头,因为是基于tcp协议去做的)

客户端点击连接--->调用connect三次握手完成之后(建立好了连接),调用send(fd, buffer, length, 0)--->这就是客户端的request(实现websocket客户端的时候也就是定义好request的内容)

  1. websocket头--->发送数据、接收数据

httphttps协议在发送数据的时候都会有一个协议头,协议头后面跟着的才传输内容,同样websocket协议也有websocket协议头--->长度为6位

  1. 断开连接

服务端会接收到6位长度的字节头,里面不带数据

任何一个协议设计都要设计好上述三个环节

WebSocket连接细节自问自答

  1. 为什么要握手?--->websocket基于tcp,为什么websockettcp的连接之上还需要一个握手?

tcp协议中客户端和服务器已经建立好连接了.websocket为什么还要建立握手?

握手解决的问题:

  • 客户端和服务器有多个协议,那么就有多个协议的版本.可以通过握手解决连接走哪个版本的协议

也可以在发送协议的时候每一个数据包前4bit都是协议版本--->握手的好处是不需要每一个数据包都确定是哪个协议

  • 兼容httphttps协议

websocket协议首先是要兼容web的协议,也就是httphttps协议,那么websocket当中的tcp协议就做到了这一点,所以websocket要在tcp连接之后在发送握手协议

  • 验证双方的身份是否合法

关注编码

web验证身份--->authority

webscoket验证身份--->Sec-WebSocket-Key(字符串末尾有等号或者多个等号(base64编码))--->服务端根据发送的sec-websocket-key转换成sec-websocket-accept,客户端接接收到responseaccept以后去和key比对,不符合就会断开连接

注意:

协议当中没有定义key的长度,所以需要GUID,这个GUID起到的是填充的作用,因为accept需要用keySHA-1 hash运算

  1. 为什么要断开?--->tcp连接也可以检查出已经断开连接,websocket为什么还要做一次断开?

websockettcp之上还做了一次断开

WebSocket两个难点

  1. 哪里体现出来使用的是websocket协议?

Upgrade: websocket

  1. 如何进行双方身份验证?

使用Sec-WebSocket-Key加上GUID进行SHA-1 Hash运算,得到Accept

WebScokect协议在HandShake的时候和传输数据的时候为什么字节头不一样

  1. HandShake是基于tcp协议进行的三次握手,所以没有6字节的字节头

WebSocket协议传输字节图:

分析:--->最上面0、1、2、3是byte字节,0、1、2、3、4、5、6...是bit

  • 一共有32个bit长度,四个字节(一个字节8bit)--->看上述图要上下看,Payload Data是数据,前面的是协议头

测试当中为什么会有边界值一说?

因为在传输协议当中,如果传输的数据内容长度不足一定程度的话他的协议头占用的字节会不一样,在websocket协议中,payload长度不足126,那么实际的协议头只有1字节的opetioncode操作码,1字节长度4字节掩码(总共6字节)

if (payloadLength < 126)

    sizeof websocketshake = 6; // 六字节
else if (payloadLength == 126)

    sizeof websocketshake = 8; // 八字节
else 
    sizeof websocketshake = 14; // 十四字节()
// payloadLength长度要看`bit`的长度

由上述表可以看出,payloadLength长度最长是7+64bit

10bit--->K,20bit--->M,30bit--->G,40bit--->T,50bit--P...


有了 HTTP 协议,为什么还需要 Websocket?

WebSocket 是一种基于 TCP 连接上进行全双工通信的协议,相对于 HTTP 这种非持久的协议来说,WebSocket 是一个持久化网络通信的协议。

WebSocket 是一种基于 TCP 连接上进行全双工通信的协议,相对于 HTTP 这种非持久的协议来说,WebSocket 是一个持久化网络通信的协议。

它不仅可以实现客户端请求服务器,同时可以允许服务端主动向客户端推送数据。在 WebSocket API 中,客户端和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

为什么需要 WebSocket

在 Web 应用架构中,连接由 HTTP/1.0 和 HTTP/1.1 处理。HTTP 是客户端/服务器模式中 请求一响应 所用的协议,在这种模式中,客户端(一般是浏览器)向服务器提交 HTTP 请求,服务器响应请求的资源(例如 HTML 页面)。

HTTP 是无状态的,也就是说,它将每个请求当成唯一和独立的。无状态协议具有一些优势,例如,服务器不需要保存有关会话的信息,从而不需要存储数据。但是,这也意味着在每次 HTTP 请求和响应中都会发送关于请求的冗余信息,比如使用 Cookie 进行用户状态的验证。

随着客户端和服务器之间交互的增加,HTTP 协议在客户端和服务器之间通信所需要的信息量快速增加。

从根本上讲,HTTP 还是 半双工 的协议,也就是说,在同一时刻信息的流向只能单向的:客户端向服务器发送请求(单向),然后服务器响应请求(单向)。半双工方式的通信效率是非常低的。

同时 HTTP 协议有一个缺陷:通信只能由客户端发起。

这种单向请求的特点,注定了如果服务器有状态变化,是无法主动通知客户端的。

为了能够及时的获取服务器的变化,我们尝试过各种各样的方式:

  • 轮询(polling):每隔一段时间,就发出一个请求,了解服务器有没有新的信息。不精准,有延时,大量无效数据交换。
  • 长轮询( long polling):客户端向服务器请求信息,并在设定的时间段内保持连接。直到服务器有新消息响应,或者连接超时,这种技术常常称作“挂起GET”或“搁置POST”。占用服务器资源,相对轮询并没有优势,没有标准化。
  • 流化技术:在流化技术中,客户端发送一个请求,服务器发送并维护一个持续更新和保持打开(可以是无限或者规定的时间段)的开放响应。每当服务器有需要交付给客户端的信息时,它就更新响应。服务器从不发出完成 HTTP 响应。代理和防火墙可能缓存响应,导致信息交付的延迟增加。

上述方法提供了近乎实时的通信,但是它们也涉及 HTTP 请求和响应首标,包含了许多附加和不必要的首标数据与延迟。此外,在每一种情况下,客户端都必须等待请求返回,才能发出后续的请求,而这显著地增加了延退。同时也极大地增加了服务器的压力。

什么是 WebSocket

而 Websocket 是一种自然的全双工、双向、单套接字连接,解决了 HTTP 协议中不适合于实时通信的问题。2008 年被提出,2011 年成为国际标准。

Websocket 协议能够通过 Web 进行客户端和服务器之间的全双工通信,并支持二进制数据和文本字符串的传输。

这个协议由开始的握手和之后的基本消息框架组成,是建立在 TCP 协议上的。相比于 HTTP 协议,Websocket 链接一旦建立,即可进行双向的实时通信。

其特点包括:

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

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

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

(4)可以发送文本,也可以发送二进制数据。

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

相似技术

Server-sent Events(SSE):

https://www.ruanyifeng.com/blog/2017/05/server-sent_events.html

https://www.cnblogs.com/goloving/p/9196066.html

SPDY (读作“SPeeDY”):已不再维护,由 HTTP/2 取代

https://baike.baidu.com/item/SPDY/3399551#7

WebRTC

https://baike.baidu.com/item/WebRTC/5522744

通信原理

WebSocket 链接是如何建立的?

前面说过,WebSocket 在握手阶段采用的是 HTTP 协议,Websocket 借用了 HTTP 的一部分协议来完成一次握手。(HTTP的三次握手,此处只完成一次)

HTTP 请求与响应首部

WebSocket 请求与响应首部

链接通信模拟

HTTP 轮询

首先是 ajax 轮询,其原理非常简单,让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息。

场景再现:

  • 客户端:啦啦啦,有没有新信息(Request)
  • 服务端:没有(Request)
  • 客户端:啦啦啦,有没有新信息(Request)
  • 服务端:没有。。(Response)
  • 客户端:啦啦啦,有没有新信息(Request)
  • 服务端:你好烦啊,没有啊。。(Response)
  • 客户端:啦啦啦,有没有新消息(Request)
  • 服务端:好啦好啦,有啦给你 ’ 西岭真帅’ 。(Response)
  • 客户端:啦啦啦,有没有新消息(Request)
  • 服务端:。。。没。。。。没。。没有

从上面可以看出,轮询其实就是在不断地建立HTTP连接,然后等待服务端处理,可以体现 HTTP 协议的另外一个特点,被动性。同时,http 的每一次请求与响应结束后,服务器将客户端信息全部丢弃,下次请求,必须携带身份信息(cookie),无状态性。

WebSocket

客户端通过 http(骑马)带着信请求服务器,但同时,携带了 Upgrade:websocket 和Connection:Upgrade(两根管子),服务器如果支持 WebSocket 协议(有两根管子的接口),使用 Websocket 协议返回可用信息(丢弃马匹),此后信息的传递,均使用这两个管子,除非有一方人为的将管子切断。若服务器不支持,客户端请求链接失败,返回错误信息。

Websocket 的出现,干净利落的解决了这些问题。

所以上面的情景可以做如下修改。

  • 客户端:啦啦啦,我要建立 Websocket 协议,需要的服务:chat,Websocket协议版本:13(HTTP Request)
  • 服务端:ok,确认,已升级为 Websocket协议(HTTP Protocols Switched)
  • 客户端:麻烦你有信息的时候推送给我噢。。
  • 服务端:ok,有的时候会告诉你的。
  • 客户端:balabala开始斗图balabala
  • 服务端:苍*空bala
  • 客户端:流鼻血了,我擦……
  • 服务端:哈哈哈牛XX啊哈哈哈哈
  • 服务端:笑死我了哈哈

以上是关于WebSocket网络通信协议的主要内容,如果未能解决你的问题,请参考以下文章

WebSocket协议理解

有了 HTTP 协议,为什么还需要 Websocket?

物联网5.物联网常用的通信协议 - WebSocket 协议

WebSocket 教程

WebSocket协议分析

WebSocket(基于TCP的全双工通信协议)