WebSocket是什么
Wiki上是这样介绍的:WebSocket是一种在单个TCP连接上进行全双工通讯的协议。
这里做个补充:是HTML5开始提供的一种浏览器与服务器进行全双工通讯的网络技术,属于应用层协议。它基于TCP传输协议,并复用HTTP的握手通道。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
WebSocket产生的背景
说到WebSocket产生的背景,就必须得先了解HTTP的通信机制。
HTTP的生命周期通过Request来界定,也就是一个Request 一个Response,那么在HTTP1.0中,这次HTTP请求就结束了。在HTTP1.1中进行了改进,使得有一个keep-alive,也就是说,在一个HTTP连接中,可以发送多个Request,接收多个Response。但是请记住 Request = Response , 在HTTP中永远是这样,也就是说一个request只能有一个response。而且这个response也是被动的,不能主动发起。
所以,为了创建一个具有双向通信机制的web应用时(如web IM),就只能利用http轮询的方式,分为短轮询和长轮询,具体可以学习ajax和comet技术。
轮询这种方式,有很多缺点,比如每次请求,都有很多重复的信息(较长的HTTP头),浪费很多资源和带宽,此外,这种方式会有一定的时延,对于需要即时通讯的应用是难以被接受的。
于是,就有了WebSocket协议。
WebSocket建立连接
WebSocket只需要一次握手,并且为了兼容现有的HTTP的服务端组件,在HTTP请求上做了升级完成握手。具体指的是,客户端通过HTTP请求与WebSocket服务端协商升级协议。协议升级完成后,后续的数据交换则遵照WebSocket的协议。
握手过程如下:
1. 客户端浏览器发起协议升级请求
GET ws://127.0.0.1:8080/websocketTest/user000 HTTP/1.1
Host: 127.0.0.1:8080
Connection: Upgrade
Upgrade: websocket
Origin: http://localhost:8080
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Sec-WebSocket-Key: 5J5p7v3DZ8Tosy2W0g9UYQ==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Connection:Upgrade:表示要升级协议
Upgrade:websocket:表示要升级到websocket协议。
Sec-WebSocket-Version:13:表示websocket的版本。如果服务端不支持该版本,需要返回一个Sec-WebSocket-Versionheader,里面包含服务端支持的版本号。
Sec-WebSocket-Key:与后面服务端响应首部的Sec-WebSocket-Accept是配套的,提供基本的防护,比如恶意的连接,或者无意的连接。
Sec-WebSocket-Extension:客户端通过包含一个|Sec-WebSocket-Extensions|头字段请求扩展
2. 服务端响应协议升级
HTTP/1.1 101
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Accept: py9zdlc/o6/uW2v87YlCOCY6PKo=
Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15
Date: Sat, 12 May 2018 02:50:16 GMT
Sec-WebSocket-Accept根据客户端请求首部的Sec-WebSocket-Key计算出来。
计算公式为:
将Sec-WebSocket-Key跟258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接。
通过SHA1计算出摘要,并转成base64字符串。
WebSocket优点
1. 服务器与客户端之间交换的标头信息很小,大概只有2字节
2. 客户端与服务器都可以主动传送数据给对方,真正的全双工
3. 不用频繁创建TCP请求及销毁请求,减少网络带宽资源的占用,同时也节省服务器资源
4. 支持扩展。ws协议定义了扩展,用户可以扩展协议,或者实现自定义的子协议。(比如支持自定义压缩算法等)