websocket
以及心跳检测机制
最近的一个项目需要用到 websocket 来实现实时数据的展示,之前的项目基本上没有这个需求所以自己对于 websocket
基本是一知半解的状态。要求当服务器挂起的时候能够检测到挂起中断请求,当服务器正常的时候,要及时连接,因为之前已经有很多前辈的文章对这个有过很详细的论述了,所以我只记录了自己需要学习的地方,本文章不适合作为学习websocket
的教程,如果有想要详细的学习websocket
教程的请移步阮一峰大神博客,他写的比较详细websocket 教程。
websocket
简介
- 什么是
websocket
? - 为什么要有
websocket
? - 怎么使用
websocket
? - 心跳检测机制间歇性校测服务器情况?
什么是websocket
?
WebSocket
是一种网络通信协议,更完整的解释是一种基于 TCP 的全双工通信协议,是不是感觉好像解释了又好像没有,WebSocket
是一种在单个 TCP 连接上进行全双工通信的协议。WebSocket 通信协议于 2011 年被 IETF 定为标准 RFC 6455,并由 RFC7936 补充规范。WebSocket API 也被 W3C 定为标准。 WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在websocket
API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
为什么要有websocket
?
很多网站为了实现推送技术,所用的技术都是轮询。轮询是在特定的的时间间隔(如每 1 秒),由浏览器对服务器发出 HTTP 请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而 HTTP 请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
http 还有一个比较明显的缺陷就是只能由客户端发起也就是说,如果我想要知道一条结果只能由客户端发起请求,然后服务端返回请求,做不到服务端自动的向客户端推送数据。
这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。
轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。因此,工程师们一直在思考,有没有更好的方法。websocket
就是这样发明的。 而比较新的技术去做轮询的效果是 Comet。这种技术虽然可以双向通信,但依然需要反复发出请求。而且在 Comet 中,普遍采用的长链接,也会消耗服务器资源。 在这种情况下,HTML5 定义了websocket
协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
websocket
的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
怎么使用websocket
?
通过上面的阐述我们大致了解到了为什么要有websocket
以及什么是websocket
,下面就让我们看一下,我们再代码里面应该怎么去使用websocket
实例化websocket
var ws = new WebSocket("wss://echo.websocket.org");
ws.onopen = function(evt) {
console.log("Connection open ...");
ws.send("Hello WebSockets!");
};
ws.onmessage = function(evt) {
console.log( "Received Message: " + evt.data);
ws.close();
};
ws.onclose = function(evt) {
console.log("Connection closed.");
};
websocket
相关的API
websocket
的构造函数
WebSocket 对象作为一个构造函数,
用于新建 WebSocket 实例
var ws = new WebSocket(url);
- 实例对象的
onopen
属性,用于指定连接成功后的回调函数
ws.onopen = function () {
ws.send('Hello Server!');
}
- 实例对象的
onclose
属性,用于指定连接关闭后的回调函数。
ws.onclose = function(event) {
var code = event.code;
var reason = event.reason;
var wasClean = event.wasClean;
// handle close event
};
ws.addEventListener("close", function(event) {
var code = event.code;
var reason = event.reason;
var wasClean = event.wasClean;
// handle close event
});
- 实例对象的onmessage属性,用于指定收到服务器数据后的回调函数。
ws.onmessage = function(event) {
var data = event.data;
// 处理数据
};
ws.addEventListener("message", function(event) {
var data = event.data;
// 处理数据
});
- 实例对象的send()方法用于向服务器发送数据。
ws.send('your message');
- 实例对象的onerror属性,用于指定报错时的回调函数。
socket.onerror = function(event) {
// handle error event
};
socket.addEventListener("error", function(event) {
// handle error event
});
心跳检测机制检测服务器情况?
有了上面的了解接下来就要实现我这次需要时间的功能了
- 实例化一个
websocket
对象 - 监听该对象的报错,发消息,异常信息
- 心跳检测机制,定时检测接口是否可以正常的返回,可以就继续操作,如有异常就关闭请求避免多次无用的请求。
var lockReconnect = false;//避免重复连接
var wsUrl = "wss://echo.websocket.org";
var ws;
var tt;
function createWebSocket(url)
{
try {
ws = new WebSocket(url);
init();
} catch (e) {
reconnect(url);
}
}
function init()
{
ws.onclose = function ()
{
console.log("websocket关闭了");
reconnect(url);
}
ws.onopen = function ()
{
console.log("websocket打开了");
heartCheck(url);
}
ws.onerror = function ()
{
console.log("websocket报错了");
reconnect(url);
}
ws.onmessage = function ()
{
//能收到消息说明链接正常
heartCheck(url);
}
}
function reconnect(url)
{
//如果连接被锁定了,就说明当前的链接是正常的
if (lockReconnnet) {
return;
}
lockReconnnet = true;
//清除定时器
tt && clearTimeout(tt);
tt = setTimeout(() =>
{
createWebSocket(url);
lockReconnnet = false;
}, 4000)
}
var heartCheck = {
timeout: 3000,
timeOutObj: null,
serverTimeOutObj: null,
start: function ()
{
var self = this;
this.timeOutObj && clearTimeout(this.timeOutObj);
this.serverTimeOutObj && clearTimeout(this.serverTimeOutObj)
this.timeOutObj = setTimeout(() =>
{
ws.send("发送数据");
self.serverTimeOutObj = setTimeout(() =>
{
ws.onclose();
}, self.timeout)
}, self.timeout)
}
}
createWebSocket(wsUrl);
当创建webSocket
链接的时候,
- 会触发
ws.onopen
- 心跳检测函数
heartCheck
heartCheck
给服务端发了请求,如果服务端是通常的,那么就会触发ws.onmessage
里面的heartCheck.start()
这次触发会清除掉两个定时器,内层定时器不会被触发了。如果没有在规定时间内返回讯息,那么就会出发内层定时器,连接关闭;- 连接关闭的时候,触发了
ws.onclose
里面的reconnect
函数,重新连接触发1,2,3的步骤
结束语
这只是我的业务需要,中间很多也是参考了前辈的文章才写出来的,websocket在实现实时数据这个方面还是很实用的。如果中间文章有任何问题欢迎评论区随时指正。
本文使用 markdown.com.cn 排版