话不多说,上需求,公司项目:做一个停车场显示车辆余位的大屏,就显示余位数可以了,很简单嘛,直接websocket就完事了,因为之前帮着一起改过一款即时通软件,里面用的就是websocket,所以感觉没啥难的,文档稍微瞄了瞄就开始写代码,结果自己踩了一个坑,然后仔细看了看文档,才从坑里爬出来,所以不熟悉的东西做的时候也要重视下,不能小看他们了,好啦,复盘检讨完毕。
所以呢,我们好好学一下Websocket,let's go!
Websocket的诞生
在客户端和服务端中交互中最常见的是Http协议,由客户端主动发起请求给服务端,服务端收到请求后再把数据传给客户端,但是在一些场景下,我们希望服务端主动发给我消息,这里有一个分支诞生了,那就是轮询,轮询就是客户端一直在给服务端发请求,这个操作不但效率低而且浪费资源,随之就出现了Websocket,当服务端与客户端建立连接后,服务端可以主动推消息给客户端,客户端当然也可以发消息给服务端,wow~这真是一个好东西。
轮询:
客户端:"喂,服务端你吃好饭了吗?吃好了我们一起打游戏"
服务端:"还没吃呢,等会儿"
客户端:"喂,服务端你吃好饭了吗?吃好了我们一起打游戏"
服务端:"还没吃呢,等会儿"
客户端:"喂,服务端你吃好饭了吗?吃好了我们一起打游戏"
服务端:"还没吃呢,等会儿"
客户端:"喂,服务端你吃好饭了吗?吃好了我们一起打游戏"
websocket:
客户端:"服务端,你吃好饭了,我们一起打游戏" (建立连接)
这时候客户端可以做些别的事情,等服务端吃好饭
服务端:"我吃好饭了,走,打游戏去" (服务端自己推送消息给客户端,仅需满足建立连接的条件即可)
特点
数据格式比较轻,性能开销小,通信高效
没有同源限制(跨域),客户端直接可以与任意服务器通信
协议标示符ws,加密的话就是wss
简单的一个例子
let wsUrl = "xxxxx"; // 约定好的ws地址let ws = new WebSocket(wsUrl); // 创建ws对象ws.onopen = function(msg) { console.log("连接成功", msg); // 连接成功后调用}ws.onmessage = function(msg) { console.log("收到消息", msg); // 接收到消息后调用}ws.onclose = function(msg) { console.log("连接已关闭",msg); // 连接关闭后调用}ws.onerror = function(err) { console.log("连接错误", err); // 连接发生错误时调用}ws.send(msg) ; // 客户端往服务端发送消息
这样一个简单的例子就完成了,还有其他的方法或属性可以参考Api。
你以为websocket相关的知识这些就结束了?No,这里面还有一个心跳机制。
心跳机制
客户端和服务端保持长连接中,因为一些缘故可能导致连接失效,服务端也有可能没有去触发onclose事件,那么客户端就不知道其实连接已经断开了,这时候就要去重连,那么心跳机制就是检测是否还在连接的方案。
心跳机制:仿佛心跳一般,每隔一个时间去告诉服务端,"哦,我亲爱的服务端,我们还连着吗?断了的话,我就要去重连了"
具体的心跳包和重连可以参考下面的文章,两位优秀的作者讲的很不错。
实现原理就是定时器每隔一段时间去ws.send(),send失败了,则和服务端重新建立连接。
理解Websockeet心跳及重连机制:https://www.cnblogs.com/tugenhua0707/p/8648044.html
Websocket心跳检测和重连机制:https://www.cnblogs.com/buxiugangzi/p/11379883.html
Vue使用websocket进行心跳连接:https://www.jianshu.com/p/09b91b9a778f