WebSocket
简单来说,WebSocket是一种协议,与HTTP协议一样位于应用层,都是TCP/IP协议的子集。HTTP协议是单向通信协议,只有客户端发起HTTP请求,服务端才会返回数据。而WebSocket协议是双向通信协议,在建立连接之后,客户端和服务器都可以主动向对方发送或接受数据。WebSocket协议建立的前提需要借助HTTP协议,建立连接之后,持久连接的双向通信就与HTTP协议无关了。
WebSocket协议的目标是在一个独立的持久连接上提供全双工双向通信。客户端和服务器可以向对方主动发送和接受数据。在JS中创建WebSocket后,会有一个HTTP请求发向浏览器以发起请求。在取得服务器响应后,建立的连接会使用HTTP升级将HTTP协议转换为WebSocket协议。也就是说,使用标准的HTTP协议无法实现WebSocket,只有支持那些协议的专门浏览器才能正常工作。
由于WebScoket使用了自定义协议,所以URL与HTTP协议略有不同。未加密的连接为ws://,而不是http://。加密的连接为wss://,而不是https://。
使用JavaScript是实现WebScoket协议相对简单,以下是WebSocket APIs
// 打开WebSocket, 传递的参数url没有同源策略的限制。
let websocket = new WebSocket(url)
// 监听open事件,在成功建立websocket时向url发送纯文本字符串数据(如果是对象则必须序列化处理)。
websocket.onopen = () => {
if (websocket.readyState === WebSocket.OPEN) {
websocket.send('hello world')
}
}
// 监听message事件,在服务器响应时接受数据。返回的数据存储在事件对象中。
websocket.onmessage = e => {
let data = e.data
console.log(data)
}
// 监听error事件,在发生错误时触发,连接不能持续。
websocket.onerror = () => {
console.log('websocket connecting error!!')
}
// 监听close事件,在连接关闭时触发。只有close事件的事件对象拥有额外的信息。可以通过这些信息来查看关闭状态
websocket.onclose = e => {
let clean = e.wasClean // 是否已经关闭
let code = e.code // 服务器返回的数值状态码。
let reason = e.reason //服务器返回的消息。
}
注意,WebScoket不支持DOM2语法为事件绑定事件处理程序,因此必须使用DOM0级语法来每个事件绑定事件处理程序
// correct!
websocket.onerror = () => {}
// error!
websocket.addEventListener('error', () => {})
WebSocket是应用层协议,是TCP/IP协议的子集,通过HTTP/1.1协议的101状态码进行握手。也就是说,WebSocket协议的建立需要先借助HTTP协议,在服务器返回101状态码之后,就可以进行websocket全双工双向通信了,就没有HTTP协议什么事情了。
参照wiki握手协议的例子:并对一些字段进行说明。
Connection:Connection必须设置为Upgrade,表示客户端希望连接升级
Upgrade:Upgrade必须设置为WebSocket,表示在取得服务器响应之后,使用HTTP升级将HTTP协议转换(升级)为WebSocket协议。
Sec-WebSocket-key:随机字符串,用于验证协议是否为WebSocket协议而非HTTP协议
Sec-WebSocket-Version:表示使用WebSocket的哪一个版本。
Sec-WebSocket-Accept:根据Sec-WebSocket-Accept和特殊字符串计算。验证协议是否为WebSocket协议。
Sec-WebSocket-Location:与Host字段对应,表示请求WebSocket协议的地址。
HTTP/1.1 101 Switching Protocols:101状态码表示升级协议,在返回101状态码后,HTTP协议完成工作,转换为WebSocket协议。此时就可以进行全双工双向通信了。
WebSocket协议的浏览器兼容性较好。