var ShortPollingNotification = {
datasInterval: null,
subscribe: function() {
this.datasInterval = setInterval(function() {
Request.getDatas().then(function(res) {
window.ChatroomDOM.renderData(res);
});
}, TIMEOUT);
return this.unsubscribe;
},
unsubscribe: function() {
this.datasInterval && clearInterval(this.datasInterval);
}
}
shortPolling
下面是对应的请求,注意左下角的请求数量一直在变化
shortNetwork
在上图中,每隔1s就会发送一个请求,看起来效果还不错,但是如果将timeout的值设置成5s,效果将大打折扣,如图:
shortPolling5s
长轮询(Long Polling)
长轮询的基本原理:客户端发送一个请求,服务器会hold住这个请求,直到监听的内容有改变,才会返回数据,断开连接,客户端继续发送请求,重复以上步骤。或者在一定的时间内,请求还得不到返回,就会因为超时自动断开连接。
longPolling
长轮询是基于轮询上的改进版本,主要是减少了客户端发起Http连接的开销,改成了在服务器端主动地去判断所关心的内容是否变化,所以其实轮询的本质并没有多大变化,变化的点在于:
-
对于内容变化的轮询由客户端改成了服务器端(客户端会在连接中断之后,会再次发送请求,对比短轮询来说,大大减少了发起连接的次数)
-
客户端只会在数据改变时去作相应的改变,对比短轮询来说,并不是全盘接收
代码实现
// 客户端
var LongPollingNotification = {
// …
subscribe: function() {
var that = this;
// 设置超时时间
Request.getV2Datas(this.getKey(),{ timeout: 10000 }).then(function(res) {
var data = res.data;
window.ChatroomDOM.renderData(res);
// 成功获取数据后会再次发送请求
that.subscribe();
}).catch(function (error) {
// timeout 之后也会再次发送请求
that.subscribe();
});
return this.unsubscribe;
}
// …
}
笔者采用的是express,默认不支持hold住请求,因此用了一个express-longpoll的库来实现。
下面是一个原生不用库的实现(这里只是介绍原理),整体的思路是:如果服务器端支持hold住请求的话,那么在一定的时间内会自轮询,然后期间通过比较key值,判断是否返回新数据
-
客户端第一次会带一个空的key值,这次会立即返回,获取新内容,服务器端将计算出的contentKey返回给客户端
-
然后客户端发送第二次请求,带上第一次返回的contentKey作为key值,然后进行下一轮的比较
-
如果两次的key值相同,就会hold请求,进行内部轮询,如果期间有新内容或者客户端timeout,就会断开连接
-
重复以上步骤
// 服务器端
router.get(‘/v2/datas’, function(req, res) {
const key = _.get(req.query, ‘key’, ‘’);
let contentKey = chatRoom.getContentKey();
while (key === contentKey) {
sleep.sleep(5);
contentKey = chatRoom.getContentKey();
}
const connectors = chatRoom.getConnectors();
const messages = chatRoom.getMessages();
res.json({
code: 200,
data: { connectors: connectors, messages: messages, key: contentKey },
});
});
以下是用 express-longpoll 的实现片段
// mini-chatroom/public/javascripts/server/longPolling.js
function pushDataToClient(key, longpoll) {
var contentKey = chatRoom.getContentKey();
if (key !== contentKey) {
var connectors = chatRoom.getConnectors();
var messages = chatRoom.getMessages();
longpoll.publish(
‘/v2/datas’,
{
code: 200,
data: {connectors: connectors, messages: messages, key: contentKey},
}
);
}
}
longpoll.create(“/v2/datas”, function(req, res, next) {
key = _.get(req.query, ‘key’, ‘’);
pushDataToClient(key, longpoll);
next();
});
intervalId = setInterval(function() {
pushDataToClient(key, longpoll);
}, LONG_POLLING_TIMEOUT);
为了方便演示,我将客户端发起请求的timeout改成了4s,注意观察下面的截图:
longPollingNetwork
可以看到,断开连接的两种方式,要么是超时,要么是请求有数据返回。
基于iframe的长轮询模式
这种模式的具体的原理为:
-
在页面中嵌入一个iframe,地址指向轮询的服务器地址,然后在父页面中放置一个执行函数,比如
execute(data)
-
当服务器有内容改变时,会向iframe发送一个脚本
<script>parent.execute(JSON.stringify(data))</script>
-
通过发送的脚本,主动执行父页面中的方法,达到推送的效果
具体可以参看这里
Websocket
The WebSocket Protocol enables two-way communication between a client running untrusted code in a controlled environment to a remote host that has opted-in to communications from that code.
The protocol consists of an opening handshake followed by basic message framing, layered over TCP.
The goal of this technology is to provide a mechanism for browser-based applications that need two-way communication with servers that does not rely on opening multiple HTTP connections (e.g., using XMLHttpRequest or iframe and long polling).
The WebSocket Protocol attempts to address the goals of existing bidirectional HTTP technologies in the context of the existing HTTP infrastructure; as such, it is designed to work over HTTP ports 80 and 443 as well as to support HTTP proxies and intermediaries, even if this implies some complexity specific to the current environment.
特征
-
websocket是双向通信的,设计的目的主要是为了减少传统轮询时http连接数量的开销
-
建立在TCP协议之上,握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器
-
与HTTP兼容性良好,同样可以使用80和443端口
-
没有同源限制,客户端可以与任意服务器通信
-
可以发送文本,也可以发送二进制数据。
-
协议标识符是
ws
(如果加密,则为wss
),服务器网址就是 URL
websocket
关于Websocket API方面的知识,这里不再作讲解,可以自己查阅Websocket API MDN
兼容性
websocket兼容性良好,基本支持所有现代浏览器
websocket1
代码实现
笔者这里采用的是socket.io,是基于websocket的封装,提供了客户端以及服务器端的支持
// 客户端
var WebsocketNotification = {
// …
subscribe: function(args) {
var connector = args[1];
this.socket = io();
this.socket.emit(‘register’, connector);
this.socket.on(‘register done’, function() {
window.ChatroomDOM.renderAfterRegister();
});
this.socket.on(‘data’, function(res) {
window.ChatroomDOM.renderData(res);
});
this.socket.on(‘disconnect’, function() {
window.ChatroomDOM.renderAfterLogout();
});
小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
最后
看完上述知识点如果你深感Java基础不够扎实,或者刷题刷的不够、知识不全面
小编专门为你量身定制了一套<Java一线大厂高岗面试题解析合集:JAVA基础-中级-高级面试+SSM框架+分布式+性能调优+微服务+并发编程+网络+设计模式+数据结构与算法>
针对知识面不够,也莫慌!还有一整套的<Java核心进阶手册>,可以瞬间查漏补缺
全都是一丢一丢的收集整理纯手打出来的
更有纯手绘的各大知识体系大纲,可供梳理:Java筑基、MySQL、Redis、并发编程、Spring、分布式高性能架构知识、微服务架构知识、开源框架知识点等等的xmind手绘图~
T-1711037433824)]
最后
看完上述知识点如果你深感Java基础不够扎实,或者刷题刷的不够、知识不全面
小编专门为你量身定制了一套<Java一线大厂高岗面试题解析合集:JAVA基础-中级-高级面试+SSM框架+分布式+性能调优+微服务+并发编程+网络+设计模式+数据结构与算法>
[外链图片转存中…(img-t5V1LCWR-1711037433825)]
针对知识面不够,也莫慌!还有一整套的<Java核心进阶手册>,可以瞬间查漏补缺
[外链图片转存中…(img-l5BCzU7A-1711037433825)]
全都是一丢一丢的收集整理纯手打出来的
更有纯手绘的各大知识体系大纲,可供梳理:Java筑基、MySQL、Redis、并发编程、Spring、分布式高性能架构知识、微服务架构知识、开源框架知识点等等的xmind手绘图~
[外链图片转存中…(img-FqI6qmHd-1711037433826)]
[外链图片转存中…(img-NejEmbN1-1711037433826)]