之前在用 Charles 抓取游戏数据包的时候遇到的缩写为“ws”的协议,一查是 WebSocket 协议,之前没有接触过,于是小小地学习了一下。
一、简介/与 HTTP 协议的联系
WebSocekt 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。按照个人理解,就是 HTTP 协议为了支持长连接所产生的一个“补丁”,但并不完全相等。
在 HTTP 协议中,连接(Connection)的生命周期由请求(Request)和响应(Response)界定(HTTP1.0)。在 HTTP1.1 中则进行了改进,由多个请求(Request)和响应(Response)来达到近似 keep-alive 的状态,但是 Request 和 Response 总是一一对应的,而且 Response 是被动的,不能主动发起。而达到持久连接(keep-alive),常用的方法是轮询与长轮询,但二者都需要浪费很多的 HTTP 资源,请求的数量较大。
而 WebSocket 则优化了这一问题。首先,建立了 WebSocket 后,服务器不必在收到浏览器(客户端)的 Request 后才能发送消息给浏览器(客户端),即服务器有自己的“主动权”来决定何时发送消息。这种方式使得只需要经过一次 HTTP 请求,就可以做到持久连接(keep-alive)。简单来说,就是有了信息就会通知,而不是周期性地询问是否有信息。
二、握手流程
为了建立一个 WebSocket 连接,浏览器(客户端)发送一个 WebSocket 握手 Request,作为回应,服务器回复一个 WebSocket 握手 Response,如下面例子(摘自 Wikipedia):
客户端 Request:
GET/chatHTTP/1.1
Host:server.example.com
Upgrade:websocket
Connection:Upgrade
Sec-WebSocket-Key:x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol:chat, superchat
Sec-WebSocket-Version:13
Origin:http://example.com
以下字段表面发起的是 WebSocket 协议,而不是 HTTP :
Upgrade:websocket
Connection:Upgrade
Sec-WebSocket-Key 主要是防止未授权的跨域脚本攻击(简单来说就是验证身份用),Sec-WebSocket-Protocol 则是自定义字符串,用来告知所需服务,Sec-WebSocket-Version 即是协议版本。
Sec-WebSocket-Key:x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol:chat, superchat
Sec-WebSocket-Version:13
服务器 Response:
HTTP/1.1101Switching Protocols
Upgrade:websocket
Connection:Upgrade
Sec-WebSocket-Accept:HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol:chat
依然是固定的,用来回应身份验证,和告知协议切换(Upgrade)。
握手完成后,就可以按前文所说的进行持久连接通信了。
三、WebSocket的缺陷
浏览器兼容问题、开发成本的提高以及新的协议生态不成熟是主要缺陷,且服务器长时间维护持久连接需要很大的成本。
另外,WebSocket 在用于双向传输、推送消息方面能够做到灵活、简便、高效,但在普通的 Request - Response 过程中并没有太大用武之地,比起普通的 HTTP 请求来反倒麻烦了许多,甚至更为低效。
网友评论