WebSocket
WebSocket是一种在单个TCP连接上进行全双工通信的协议,本质上是基于TCP的应用层协议。WebSocket解决了HTTP协议的一个缺陷:通信只能由客户端发起,不具备服务器推送能力。WebSocket允许服务端主动向客户端推送数据,双向平等对话。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输,属于服务器推送技术的一种。WebSocket的特点有:1.建立在TCP协议之上,服务器端的实现比较容易。2.与HTTP协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用HTTP协议,能通过各种HTTP代理服务器,握手时不容易被屏蔽。3.数据格式轻量,性能开销小,通信高效。4.可以发送文本和二进制格式数据。5.没有同源限制,客户端可以与任意服务器通信。6.协议标识符是ws(如果加密,则为wss),服务器网址就是URL。
WebSocket在2011年成为国际标准。在HTML5标准中增加了有关WebSocket协议的相关API,所以只要实现了HTML5标准的客户端,就可以与支持WebSocket协议的服务器进行全双工的持久通信。在WebSocket出现以前,创建一个和服务端进行双通道通信的web应用需要依赖HTTP协议进行不停地“轮询”。导致服务端被迫维持来自每个客户端的大量不同的连接,大量的轮询请求会造成高开销,比如会带上多余的header,造成无用的数据传输。
WebSocket的应用场景:即时聊天通信、多玩家游戏、在线协同编辑、实时数据流的拉取与推送、体育/游戏实况、实时地图位置、即时web应用程序、游戏应用程序、聊天应用程序。
虽然HTTP/2也具备服务器推送功能,但HTTP/2只能推送静态资源,无法推送指定的信息。
WebSocket是通过HTTP进行握手建立连接的,依靠 HTTP 响应101进行协议升级转换。TCP连接建立好之后,不再需要HTTP协议。
GET /chat HTTP/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
Upgrade: websocket;
Connection: Upgrade;
用来告诉服务器,发起的请求要用WebSocket协议。Sec-WebSocket-Key
是客户端生成的一组16位的base64编码的随机数(拼接服务端和客户端生成的字符串,进行SHA1哈希算法,再用base64编码),用于标识这次连接。Sec-WebSocket-Version
表示客户端WebSocket的协议版本号。Sec_WebSocket-Protocol
表示使用的协议列表。
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chat
响应头里的Sec-WebSocket-Accept值是将Sec-WebSocket-Key字段的值经过固定算法加密得到的,供客户端进行校验。Sec-WebSocket-Protocol表示确定使用的协议。
关于webSocket的断线重连问题。当连接断开时,只有客户端主动访问服务端才能实现重连。客户端会定时给服务端发送心跳包,客户端通过setInterval定时任务每隔3秒钟调用一次reconnect函数,reconnect会通过socket.readyState来判断这个websocket连接是否正常。如果不正常就会触发定时连接,每4s重试一次,直到连接成功。如果在指定的时间内没有收到服务器端返回心跳响应消息,因此说明连接断开。客户端需要通过onclose 关闭连接,服务端再次上线时需要清除双方的数据,若不清除会造成所有请求都会被视为离线。
解决断线问题的两个方案:1.修改Nginx配置信息。2.WebSocket发送心跳包。