目录
第三方协议:websocket
websocket简介
为什么要有websocket?
websocket协议是应用层协议之一,既然这种协议会出现,那么也就意味着它是在某些特殊场景下弥补了一些其他应用层协议的缺点。
所以关于为什么要有websocket协议,我们首先要聊聊最常见的协议http/https,它们没有解决的一些问题!
我们都知道,http协议是如何建立起连接的呢?
- http协议规定,首先由客户端向服务器发送一个http请求, 服务器收到后,根据客户端的http请求,返回给客户端一个http应答!
- 补充:来回一次报文发送,http双方通信连接就会被关闭,这也意味着http协议在通常情况下是无连接或短连接的协议!
http协议上述建立连接的方式带来了一个问题:必须由客户端主动向服务器发送请求报文,服务器无法主动给客户端发送消息!这也就意味着http协议是一个单向通信的协议
而网页的即时聊天或者像我们接下来做的项目“五子棋游戏”这样的程序都是非常依赖服务器给客户端发送消息的!
若我们想要用http协议来完成这个功能,那么只能是客户端等待一段时间之后,主动向服务器询问是否有消息。也就是基于轮询的策略。
轮询策略带来了几个弊端:
- 消息不够实时:客户端是按一定的时间间隔向服务器发送轮询的,那么从消息准备就绪到服务器收到轮询之间肯定有一定的时间间隔。这样的话就影响了整体的效率!
- 成本过高:轮询意味着客户端需要不断发送请求到网络中,而大部分的请求都是无意义的,即服务器还未准备就绪的。
基于上述的种种,最终产生了websocket协议,很明显,websocket协议是为了解决http协议的弊端,这两种协议具有强相关。所以后面我们说websocket协议通常是由http协议切换过来的!
websocket特点
websocket协议与http协议相比,主要具有以下特点:
- websocket协议支持双向通信,即服务器可以主动给客户端发送消息,客户端也可以主动给服务器发送消息
- websocket协议是一种长连接协议,通常与TCP协议相同,websocket会为通信双方建立长时间的连接,使得通信双方通信时不再需要频繁建立连接。这降低了延迟,提高了实时性,使得数据可以更快地传输到客户端。
websocket协议切换
websocket协议是由http协议切换过来的,整体切换如下图:
整体协议切换一共分为三步:
- 第一步:TCP三次握手建立连接
- 第二步:通过http报文由http协议切换到websocket协议
- 第三步:websocket协议格式通信
TCP三次握手建立连接
不管是websocket协议还是http协议,都是基于TCP协议的应用层协议。
所以对于websocket协议来说,它需要为通信双方建立一个长连接,最好的方式就是TCP的方式
http协议切换至websocket协议
协议的切换,是通过http报文的方式实现的。即客户端向服务器发送http请求,服务器给客户端http应答,之后进行协议切换。
但不同的是,协议切换的请求和应答的格式不再与普通http报文格式相同
协议切换请求报文的格式:
- "GET /ws HTTP/1.1":该行表示GET方法,ws是websocket的缩写
- "Connection:Upgrade":该行表示客户端希望升级当前的HTTP连接到一个新的协议
- "Upgrade:WebSocket":该行表示升级的协议名称为WebSocket
- "Sec-WebSocket-Version:xxx":该行表示升级的协议版本为xxx
- "Sec-WebSocket-Key:xxx":是一个由客户端(通常是浏览器)随机生成的Base64编码值。这个值在WebSocket握手请求中发送给服务器,用于确保客户端和服务器之间的连接是安全的,并且不是由恶意软件或未授权的第三方建立的。
协议切换应答报文的格式:
- "HTTP/1.1 101 xxx":其中101是响应状态码,即告诉客户端支持WebSocket协议
- "Connection:Upgrade":与请求报文对应字段含义相同
- "Upgrade:WebSocket":与请求报文对应字段含义相同
- "Sec-WebSocket-Accept":Sec-WebSocket-Accept是服务器在WebSocket握手过程中,根据客户端发送的Sec-WebSocket-Key字段,通过一定的算法计算并返回给客户端的一个响应头字段。它用于验证服务器是否理解并接受客户端发起的WebSocket连接请求,同时也作为WebSocket连接安全性的一个基本保障。
接下来的内容,就是对websocket协议格式段进行介绍!
websocket协议格式段
websocket协议格式段主要如下图:
FIN(1bit)
- WebSocket支持将长消息切割成若干帧发送,切分后,前边的帧的FIN字段均为0,最后一个帧的FIN为1。
- 当消息没有分段时,FIN标志位为1。