-
WebSocket:HTTP上Socket通信规范
-
Socket:套接字,格式:ip:端口号,网络中不同主机间应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上通信进程的一端,提供了应用层进程利用网络协议交换数据的机制。
-
为什么要有WebSocket:
WebSocket 是针对HTTP“请求-应答”通信模式的缺点而诞生的。”请求-应答“是一种“半双工”的通信模式,可以双向收发数据,但同一时刻只能有一个方向有工作,传输效率低,它同时也是一种被动的通信模式,服务器只能被动响应客户端的请求,无法主动向客户端发送数据。所以HTTP难以应用在动态页面,即时消息,网络游戏等要求”实时通信“的领域。WebSocket原来是HTML5的一部分,后来自立门户,形成了一个单独的标准,RFC文档编号是6455。
-
额外科普一下单工、半双工、全双工
数据通常是在两个站(点对点)之间进行传输,按照数据流的方向可分成三种传输模式:单工、半双工、全双工
-
单工:图(a),数据在两点之间只支持数据在一个方向传输,并且这个方向不能改变,举例:电视,广播
-
半双工:图(b),数据在两点之间同一时间内只支持数据在一个方向传输,这个方向可以改变,举例:对讲机
-
全双工:最下面那个图,数据在两点之前同一时间内支持数据双向传输,举例:电话通话
注意:前面说“请求-应答”模式是一种“半双工”的传输模式,这里打了引号,只是类比助于理解,“请求-应答”模式在HTTP里,传输的数据是一来一回的,而半双工概念是数据可以来回,同一时间内不允许同时来回,举个例子的话,假设A和B用对讲机说话,半双工:A说完,B听到A说的话,A可以不等B说话接着说,但是对于“请求-应答”模式,则是A说完,B必须要回,A或B才可以再说,且说完必须得到对方回应,所以“请求-应答”模式可以算是半双工范围里的一种特殊情况,二者并不能打等号。
WebSocket的特点
-
WebSocket是一个“全双工”的通信协议,与TCP一样,客户端和服务器都可以随时向对方发送数据,“实时通信”的效率也就高了。
-
WebSocket采用二进制帧结构,语法语义与HTTP完全不兼容,但因为它的主要运行环境是浏览器,为了便于推广和应用,在使用习惯上尽量向HTTP靠拢,这就是它名字里“Web”的含义。
-
服务发现方面,WebSocket没有使用TCP的“IP地址+端口号”,而是沿用HTTP的URI格式,开头协议名不是http,而是引入两个新名字:“ws"和"wss”,分别表示明文和加密的WebSocket协议。
-
WebSocket默认端口也选择了80和443,因为现在互联网上的防火墙屏蔽了绝大多数端口,只对80和443端口放行,所以WebSocket就可以“伪装”成HTTP协议,与服务器建立连接。
WebSocket的帧结构
-
长度:不固定,最少2个字节,最多14个字节
开头两字节是必须的,
-
第一字节第1位FIN是消息结束标志位,一个消息可以拆成多个帧,接收方看到“FIN”后,就把前面的帧拼起来,组成完整的消息;第2-4位是保留位,目前没有意义,但必须是0;第一个字节的后四位叫Opcode,表示操作码,其实就是帧类型,1表示帧内容是纯文本,2表示帧内容是二进制数据,8是关闭连接,9和10分别是连接保活的PING和PONG(WebSocket协议里的PING和PONG帧对于保持长连接很重要,可以让链路上总有数据在传输,防止被服务器,路由,网关认为是“无效链接”而意外关闭)。
-
第二个字节第1位是掩码标志位MASK,表示帧内容是否使用异或操作做简单加密,目前WebSocket标准规定,客户端发送数据必须使用掩码,服务器发送则必须不用掩码。第二个字节后7位是Payload len,表示帧内容长度,它是另一种变长编码,最少7位,最多7+64位,也就是额外增加8字节,所以WebSocket帧最大是264,长度字段后面是Masking-key,掩码秘钥,是由MASK决定的,如果使用掩码就是4个字节的随机数,否则就不存在。
WebSocket帧头 结束标志位+操作码+帧长度+掩码
WebSocket握手 WebSocket同样也有个握手过程,握手完成之后才能正式收发数据,WebSocket利用了HTTP本身“协议升级”特性,“伪装”成HTTP,这样就能绕过浏览器沙盒,网络防火墙等等限制,WebSocket握手是一个标准的HTTP GET请求,但要带上两个协议升级的专用头字段:
1、 Connection:Upgrade表示要求协议升级,
2、Upgrade:websocket,表示要升级成WebSocket协议,
为防止HTTP错识别成WebSocket,握手消息增加了两个额外的认证用头字段,
3、Sec-WebSocket-Key:一个Base64编码的16字节随机数,作为简单的认证秘钥,
4、Sec-WebSocket-Version:协议版本号,当前必须是13,
当服务器收到HTTP报文,看到上面这四个字段,不是普通GET请求,而是WebSocket的升级请求,而是构造一个特殊的“101 Switching Protocols”响应报文,通知客户端,接下来就不用HTTP了,全改用WebSocket协议通信。WebSocket握手响应报文也是有特殊格式的,要用字段Sec-WebSocket-Accept验证客户端请求报文,格式为:
encode_base64(
sha1( Sec-WebSocket-Key + ‘258EAFA5-E914-47DA-95CA-C5AB0DC85B11’ ))
这个258EAFA5-E914-47DA-95CA-C5AB0DC85B11为专用UUID
-
浏览器是一个"沙盒"环境,有很多限制,不允许建立TCP连接收发数据,而有了WebSocket,我们就可以在浏览器里与服务器直接建立“TCP连接”,而获得更多的自由。不过由于过于“原始”,用户必须自己管理连接,缓存,状态,开发上比HTTP复杂得多。