WebSocket协议(rfc6455)原文地址: https://datatracker.ietf.org/doc/html/rfc6455
考虑网页中的以下场景:
上述场景有一个共同特点——实时性
这种对实时性有要求的页面,会带来一些问题
比如下面的聊天场景
由于HTTP协议是请求-响应模式,请求必须在前,响应必须在后,这就导致了服务器无法「主动」的把消息告诉客户端。
开发者想了很多办法来解决这一问题
当然终极解决方案自然是WebSocket,但了解过去的一些做法、参观前辈们经历的痛苦还是有益的。
短轮询是一种「话痨式」的方式
客户端每隔一小段时间就向服务器请求一次,询问有没有新消息
客户端服务器一段时间后...一段时间后...一段时间后...一段时间后...有新消息吗?没有新消息吗?没有新消息吗?有,user1对你说:你好有新消息吗?没有新消息吗?没客户端服务器
实现短轮询是非常简单的,客户端只需要设置一个计时器不断发送请求即可
这种方案的缺陷是非常明显的:
我们的前辈在有限的条件下,充分发挥智慧,来解决短轮询的问题,于是演化为长轮询
客户端服务器没有消息不会响应一段时间后...没有消息不会响应一段时间后...有新消息吗?user1对你说:你好有新消息吗?user1对你说:你吃了没......客户端服务器
长轮询有效的解决了「话痨问题」,让每一次请求和响应都是有意义的
但长轮询仍然存在问题:
伴随着HTML5出现的WebSocket,从协议上赋予了服务器主动推送消息的能力
从上图可以看出:
虽然优于轮询方案,但WebSocket仍然是有缺点的:
WebSocket协议是一个高扩展性的协议,详细内容会比较复杂,这里仅讲解面试中会问到的握手协议
当客户端需要和服务器使用WebSocket进行通信时,首先会使用HTTP协议完成一次特殊的请求-响应,这一次请求-响应就是WebSocket握手
在握手阶段,首先由客户端向服务器发送一个请求,请求地址格式如下:
# 使用HTTP
ws://mysite.com/path
# 使用HTTPS
wss://mysite.com/path
请求头如下:
Connection: Upgrade /* 嘿,后续咱们别用HTTP了,升级吧 */
Upgrade: websocket /* 我们把后续的协议升级为websocket */
Sec-WebSocket-Version: 13 /* websocket协议版本就用13好吗? */
Sec-WebSocket-Key: YWJzZmFkZmFzZmRhYw== /* 暗号:天王盖地虎 */
服务器如果同意,就应该响应下面的消息
HTTP/1.1 101 Switching Protocols /* 换,马上换协议 */
Connection: Upgrade /* 协议升级了 */
Upgrade: websocket /* 升级到websocket */
Sec-WebSocket-Accept: ZzIzMzQ1Z2V3NDUyMzIzNGVy /* 暗号:小鸡炖蘑菇 */
握手完成,后续消息收发不再使用HTTP,任何一方都可以主动发消息给对方
ws:
开头的地址,请求头中要分别加入upgrade、connection、Sec-WebSocket-Key、Sec-WebSocket-Version
标记
然后,服务器收到请求后,发现这是一个 websocket 协议的握手请求,于是响应行中包含Switching Protocols
,同时响应头中包含upgrade、connection、Sec-WebSocket-Accept
标记
当客户端收到响应后即可完成握手,随后使用建立的 TCP 连接直接发送和接收消息。1. 短轮询。即客户端每隔一段时间就向服务器发送消息,询问有没有新的数据
2. 长轮询,发起一次请求询问服务器,服务器可以将该请求挂起,等到有新消息时再进行响应。响应后,客户端立即又发起一次请求,重复整个流程。
3. websocket,握手完毕后会建立持久性的连接通道,随后服务器可以在任何时候推送新消息给客户端
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。