https://www.cnblogs.com/chyingp/p/websocket-deep-in.html
https://cloud.tencent.com/developer/article/1887095
https://www.ruanyifeng.com/blog/2017/05/websocket.html
websocket是一种网络传输协议,可以在单个tcp连接上进行全双工通讯,位于osi模型的应用层(http也位于应用层)
websocket与http关系
websocket复用了http的握手通道,在http连接的基础上,客户端发起协议升级,采用的是标准的http报文格式,且只支持get方法
客户端
GET / HTTP/1.1
Host: localhost:8080
Origin: http://127.0.0.1:3000
Connection: Upgrade // 表示协议升级
Upgrade: websocket // 表示升级到websocket协议
// websocket版本,如果服务器不支持此版本,则会返回Sec-WebSocket-Version 的header,里面有所有他支持的版本
Sec-WebSocket-Version: 13
// 与服务器的Sec-WebSocket-Accept配套使用,提供基本的防护,比如无意链接、恶意连接
Sec-WebSocket-Key: w4v7O6xFTi36lq3RNcgctw==
服务器端
HTTP/1.1 101 Switching Protocols // 协议切换,完成协议升级
Connection:Upgrade
Upgrade: websocket
// 这个值与客户端Sec-WebSocket-Key有关,通过SHA1散列算法获取摘要信息值,并转成base64字符串
Sec-WebSocket-Accept: Oy4NRAQ13jhfONC7bP8dTKb4PTU=·
websocket的api
var ws = new WebSocket('ws://localhost:8080');
执行了上面的语句,websocket就会进行连接
websocket.readyState
返回实例对象的当前状态
- 0(connecting):正在连接
- 1(open):连接成功可以通信
- 2(closing):正在关闭
- 3(closed):连接已关闭,或打开链接失败
websocket.onOpen()
用于连接成功后的回调函数
websocket.onClose()
用于连接管壁厚的回调属性
websocket.onMessage()
收到服务器数据后的回调函数
websocket.send()
向服务器发送数据的函数
websocket.error()
用于报错时的回调函数
websocket.bufferedAmount
判断发送是否结束(表示还有多少二进制字节的数据没有发送出去)
var data = new ArrayBuffer(10000000);
socket.send(data);
if (socket.bufferedAmount === 0) {
// 发送完毕
} else {
// 发送还没结束
}
websocket优点
- 基于tcp协议基础上的,服务器端实现起来比较容易
- 与http有良好的兼容性,能够通过http代理(握手阶段采用http协议,不容易被屏蔽)
- 数据格式比较轻量,开销小
- 没有同源限制,客户端可以与任意服务器通信
轮询(短轮询)、长轮询和websocket区别
image.png image.png轮询(短轮询):浏览器每隔一段时间向服务器发送一次请求,服务器返回最新的数据给浏览器
长轮询:客户端发器请求,服务器端在收到后,会不直接进行响应,将请求挂起,然后判断请求的数据是否有更新,或者超时才会返回给客户端。 eg:comet的实现方式之一,另一种(http://www.52im.net/thread-336-1-1.html%235)
websocket:全双工协议,服务器端游数据更新后可以直接发消息给客户端
代理缓存污染攻击(ws引入掩码计算为了防止此攻击)
- 攻击者发送ws协议升级到攻击者服务器
- 升级请求发送到了代理服务器,经攻击者服务器响应后,代理服务器将响应回复给攻击者,连接通道打通
- 攻击者通过WebSocket向攻击者服务器发送数据,其中包含被攻击资源的地址,以及一个伪造的host(指向被攻击资源的服务器)
- 代理服务器会缓存数据,当下一次被攻击者发送请求时,会直接将缓存数据发给被攻击者
只能说不能完全防范,但是加大了难度
网友评论