http通讯只能一来一回,不能直接回包,因而出现了websocket实时通信web
在websocket没有出现以前,总会有一些需求,须要获取数据,可是这些数据殊不知道哪一个时间点才能获取到,因而,你们使用了轮询来解决服务器推送的问题。浏览器
HTTP协议只能从客户端发出请求,服务器处理返回请求(这里能够看下图),可是服务器不能主动给客户端发送请求,因而解决服务器推送的问题,就只能靠轮询了。服务器
轮询分为两种websocket
短轮询:定时发送http请求socket
长轮询:发送请求直到收到消息or超时后继续发送下一个请求加密
可是,轮询并不能完美的解决服务器推送的问题spa
websocket的出现,就是为了解决服务器推送的问题。3d
WebSocket是HTML5开始提供的一种在单个 TCP 链接上进行全双工(通讯双方既是接收方也是发送方,两端设备能够同时发送和接收数据)通信的协议。code
websocket的连接仍是比较简单的,只要进行一次握手,就能够进行后续的通信了,这里分为三步:cdn
在第一步的时候进行了握手,这里来看一下请求的详情
// 请求
GET / HTTP/1.1
Upgrade: websocket // 升级为websocket协议
Connection: Upgrade
Host: localhost:3000 // 请求host
Origin: http://binnie.com // 请求来源
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ== // 用于后续计算accept
Sec-WebSocket-Version: 13 // websocket版本号
复制代码
// 回包
HTTP/1.1 101 Switching Protocols // 101表示连接成功
Upgrade: websocket // 与请求对应
Connection: Upgrade
// 使用key计算得来,尽可能避免普通HTTP请求被误认为Websocket协议
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
复制代码
WebSocket协议使用帧(Frame)收发数据
客户端发送给服务端的帧必须经过4字节的掩码(Masking-key)加密,服务端收到消息后,用掩码对数据帧的Payload Data进行异或运算解码获得数据,若是服务端收到未经掩码加密的数据帧,则应该立刻关闭该WebSocket。
服务端发给客户端的数据则不须要掩码加密,客户端若是收到了服务端的掩码加密的数据,则也必须关闭它。
上图为websocket的帧格式,下面咱们一个个来分析
这里从左往右看,横向为32位(bit)
因此,websocket传递数据时最小的请求头为 FIN+RSV1-3+opcode+MASK+Payload len+Masking-key = 6 byte(字节),剩下的就都是实际数据,相比于http头部小得多。
websocket是很好的实时双向通信,不过兼容性只到ie10,因此不支持websocket的浏览器就只能使用轮询等方法来兼容。
因为低版本浏览器不支持websocket,须要使用轮询来兼容,因而出现了不少websocket库,后面再分析websocket库的实现。