、XHTML与HTML的区别
文档结构
XHTML DOCTYPE 是强制性的
<html>中的 XML namespace 属性是强制性的
<html>、<head>、<title>以及 <body>也是强制性的
元素语法
XHTML 元素必须正确嵌套
XHTML 元素必须始终关闭
XHTML 元素必须小写
XHTML 文档必须有一个根元素
属性语法
XHTML 属性必须使用小写
XHTML 属性值必须用引号包围
XHTML 属性最小化也是禁止的
二、HTML5中一些新特性
用于绘画的 canvas 元素
用于媒介回放的 video 和 audio 元素
对本地离线存储的更好的支持
新的特殊内容元素,比如 article、footer、header、nav、section
新的表单控件,比如 calendar、date、time、email、url、search
注意:最新版本的 Safari、Chrome、Firefox 以及 Opera 支持某些 HTML5 特性。Internet Explorer 9 将支持某些 HTML5 特性。
IE9 以下版本浏览器兼容HTML5的方法,使用本站的静态资源的html5shiv包:
三、HTML5web存储
使用HTML5可以在本地存储用户的浏览数据。
早些时候,本地存储使用的是 cookie。但是Web 存储需要更加的安全与快速. 这些数据不会被保存在服务器上,但是这些数据只用于用户请求网站数据上.它也可以存储大量的数据,而不影响网站的性能.
数据以 键/值 对存在, web网页的数据只允许该网页访问使用。
浏览器支持:
Internet Explorer 8+, Firefox, Opera, Chrome, 和 Safari支持Web 存储。
注意: Internet Explorer 7 及更早IE版本不支持web 存储.
localStorage 和 sessionStorage
客户端存储数据的两个对象为:
localStorage - 用于长久保存整个网站的数据,保存的数据没有过期时间,直到手动去除。
sessionStorage - 用于临时保存同一窗口(或标签页)的数据,在关闭窗口或标签页之后将会删除这些数据。
在使用 web 存储前,应检查浏览器是否支持 localStorage 和sessionStorage:
不管是 localStorage,还是 sessionStorage,可使用的API都相同,常用的有如下几个(以localStorage为例):
保存数据:localStorage.setItem(key,value);
读取数据:localStorage.getItem(key);
删除单个数据:localStorage.removeItem(key);
删除所有数据:localStorage.clear();
得到某个索引的key:localStorage.key(index);
四、HTML5 应用程序缓存
HTML5 -应用程序缓存=>使用文章链接跳转点这里
五、HTML5 服务器发送事件(Server-Sent Events)
Server-Sent 事件指的是网页自动获取来自服务器的更新。
以前也可能做到这一点,前提是网页不得不询问是否有可用的更新。通过服务器发送事件,更新能够自动到达。
例子:Facebook/Twitter 更新、股价更新、新的博文、赛事结果等。
所有主流浏览器均支持服务器发送事件,除了 Internet Explorer。
六、HTML5 WebSocket
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
详情和代码示例:
七、HTTP状态消息
1xx: 信息
2xx: 成功
3xx: 重定向
4xx: 客户端错误
5xx: 服务器错误
详情
八、HTTP 方法:GET 对比 POST
两种最常用的 HTTP 方法是:GET 和 POST。
什么是 HTTP ?
超文本传输协议(HTTP)的设计目的是保证客户端与服务器之间的通信。
HTTP 的工作方式是客户端与服务器之间的请求-应答协议。
web 浏览器可能是客户端,而计算机上的网络应用程序也可能作为服务器端。
举例:客户端(浏览器)向服务器提交 HTTP 请求;服务器向客户端返回响应。响应包含关于请求的状态信息以及可能被请求的内容。
GET - 从指定的资源请求数据。
POST - 向指定的资源提交要被处理的数据。
GET 方法
请注意,查询字符串(名称/值对)是在 GET 请求的 URL 中发送的:
有关 GET 请求的其他一些注释:
GET 请求可被缓存
GET 请求保留在浏览器历史记录中
GET 请求可被收藏为书签
GET 请求不应在处理敏感数据时使用
GET 请求有长度限制
GET 请求只应当用于取回数据
POST 方法
请注意,查询字符串(名称/值对)是在 POST 请求的 HTTP 消息主体中发送的:
有关 POST 请求的其他一些注释:
POST 请求不会被缓存
POST 请求不会保留在浏览器历史记录中
POST 不能被收藏为书签
POST 请求对数据长度没有要求
下面的表格列出了其他一些 HTTP 请求方法:
最后送福利了,自己是从事了五年的前端工程师,整理了一份最全面前端学习资料,只要私信:“前端"等3秒后即可获取地址,
里面概括应用网站开发,css,html,JavaScript,jQuery,Ajax,node,angular等。等多个知识点高级进阶干货的相关视频资料,等你来拿
3月30日消息,苹果 iOS 16.4 系统已经向用户推送,苹果在这个版本中开放了 Web Push API。这意味着,网站可以通过 Safari 向用户推送通知。
用 Safari 打开网页,选择下方的分享按钮,再选择添加到主屏幕,即可将网页 icon 添加到手机屏幕,当收到通知后, icon 右上角可显示通知数量。
这仅适用于添加到主屏幕的网页,网页使用 HTML5 标准 Web Push API 推送通知。
可以通过 设置>通知 来调整网页权限,对于不想收到通知的网页,可以关闭通知权限。
(8148716)
文来自“糊糊糊糊糊了”的分享,原题《实时消息推送整理》,有优化和改动。
对Web端即时通讯技术熟悉的开发者来说,我们回顾网页端IM的底层通信技术,从短轮询、长轮询,到后来的SSE以及WebSocket,使用门槛越来越低(早期的长轮询Comet这类技术实际属于hack手段,使用门槛并不低),技术手段越来越先进,网页端即时通讯技术的体验也因此越来越好。
但上周在编辑《IM扫码登录技术专题》系列文章第3篇的时候忽然想到,之前的这些所谓的网页端即时通讯“老技术”相对于当红的WebSocket,并非毫无用武之地。就拿IM里的扫码登录功能来说,用短轮询技术就非常合适,完全没必要大炮打蚊子上WebSocket。
所以,很多时候没必要盲目追求新技术,相对应用场景来说适合的才是最好的。对于即时通讯网的im和消息推送这类即时通讯技术开发者来说,掌握WebSocket固然很重要,但了解短轮询、长轮询等这些所谓的Web端即时通讯“老技术”仍然大有裨益,这也正是整理分享本文的重要原因。
[1] 新手入门贴:史上最全Web端即时通讯技术原理详解
[2] 详解Web端通信方式的演进:从Ajax、JSONP 到 SSE、Websocket
[3] Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE
对于IM/消息推送这类即时通讯系统而言,系统的关键就是“实时通信”能力。
从表面意思上来看,“实时通信”指的是:
类比于传统的C/S请求模型,“实时通信”时客户端不需要主观地发送请求去获取自己关心的内容,而是由服务器端进行“推送”。
注意:上面的“推送”二字打了引号,实际上现有的几种技术实现方式中,并不是服务器端真正主动地推送,而是通过一定的手段营造了一种“实时通信”的假象。
就目前现有的几种技术而言,主要有以下几类:
以下正文将针对这几种技术方案,为你一一解惑。
为了帮助读者更好的理解本文内容,笔者专门写了一个较完整的Demo,Demo会以一个简易聊天室的例子来分别通过上述的四种技术方式实现(代码存在些许bug,主要是为了做演示用,别介意)。
完整Demo源码打包下载:
(请从同步链接附件中下载:http://www.52im.net/thread-3555-1-1.html)
Demo的运行效果(动图):
有兴趣可以自行下载研究学习。
短轮询的实现原理:
逻辑如下图所示:
使用短轮询的优点:基础不需要额外的开发成本,请求数据,解析数据,作出响应,仅此而已,然后不断重复。
缺点也显而易见:
短轮询客户的代码实现(片段节选):
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);
}
}
PS:完整代码,请见本文“4、本文配套Demo和代码”一节。
对应本文配套Demo的运行效果如下(动图):
下面是对应的请求,注意左下角的请求数量一直在变化:
在上图中,每隔1s就会发送一个请求,看起来效果还不错,但是如果将timeout的值设置成5s,效果将大打折扣。如下图所示。
将timeout值设置成5s时的Demo运行效果(动图):
长轮询的基本原理:
逻辑如下图所示:
长轮询是基于短轮询上的改进版本:主要是减少了客户端发起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值,判断是否返回新数据。
以下是具体思路:
代码如下:
// 服务器端
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();
long poll.publish(
'/v2/datas',
{
code: 200,
data: {connectors: connectors, messages: messages, key: contentKey},
}
);
}
}
long poll.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);
PS:完整代码,请见本文“4、本文配套Demo和代码”一节。
为了方便演示,我将客户端发起请求的timeout改成了4s,注意观察下面的截图:
可以看到,断开连接的两种方式,要么是超时,要么是请求有数据返回。
这是长轮询技术的另一个种实现方案。
该方案的具体的原理为:
因不篇幅原因,在此不作深入介绍,有兴趣的同学可以详读《新手入门贴:史上最全Web端即时通讯技术原理详解》一文中的“3.3.2 基于iframe的数据流”一节。
从纯技术的角度讲:上两节介绍的短轮询和长轮询技术,服务器端是无法主动给客户端推送消息的,都是客户端主动去请求服务器端获取最新的数据。
本节要介绍的SSE是一种可以主动从服务端推送消息的技术。
SSE的本质其实就是一个HTTP的长连接,只不过它给客户端发送的不是一次性的数据包,而是一个stream流,格式为text/event-stream。所以客户端不会关闭连接,会一直等着服务器发过来的新的数据流,视频播放就是这样的例子。
简单来说,SSE就是:
SSE的技术原理如下图所示:
SSE基本的使用方法,可以参看 SSE 的API文档,地址是:https://developer.mozilla.org/en ... _server-sent_events。
目前除了IE以及低版本的浏览器不支持,绝大多数的现代浏览器都支持SSE:
(上图来自:https://caniuse.com/?search=Server-Sent-Events)
// 客户端
var SSENotification = {
source: null,
subscribe: function() {
if('EventSource'inwindow) {
this.source = newEventSource('/sse');
this.source.addEventListener('message', function(res) {
const d = res.data;
window.ChatroomDOM.renderData(JSON.parse(d));
});
}
return this.unsubscribe;
},
unsubscribe: function() {
this.source && this.source.close();
}
}
// 服务器端
router.get('/sse', function(req, res) {
const connectors = chatRoom.getConnectors();
const messages = chatRoom.getMessages();
const response = { code: 200, data: { connectors: connectors, messages: messages } };
res.writeHead(200, {
"Content-Type":"text/event-stream",
"Cache-Control":"no-cache",
"Connection":"keep-alive",
"Access-Control-Allow-Origin": '*',
});
res.write("retry: 10000\n");
res.write("data: "+ JSON.stringify(response) + "\n\n");
var unsubscribe = Event.subscribe(function() {
const connectors = chatRoom.getConnectors();
const messages = chatRoom.getMessages();
const response = { code: 200, data: { connectors: connectors, messages: messages } };
res.write("data: "+ JSON.stringify(response) + "\n\n");
});
req.connection.addListener("close", function() {
unsubscribe();
}, false);
});
下面是控制台的情况,注意观察响应类型:
详情中注意查看请求类型,以及EventStream消息类型:
PS:有关SSE更详尽的资料就不在这里展开了,有兴趣的同学可以详读《SSE技术详解:一种全新的HTML5服务器推送事件技术》、《使用WebSocket和SSE技术实现Web端消息推送》。
PS:本小节内容引用自《Web端即时通讯实践干货:如何让WebSocket断网重连更快速?》一文的“3、快速了解WebSocket”。
WebSocket诞生于2008年,在2011年成为国际标准,现在所有的浏览器都已支持(详见《新手快速入门:WebSocket简明教程》)。它是一种全新的应用层协议,是专门为web客户端和服务端设计的真正的全双工通信协议,可以类比HTTP协议来了解websocket协议。
(图片引用自《WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)》)
它们的不同点:
它们的相同点:
两者和TCP的关系图:
(图片引用自《新手快速入门:WebSocket简明教程》)
有关Http和WebSocket的关系,可以详读:
《WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)》
《WebSocket详解(五):刨根问底HTTP与WebSocket的关系(下篇)》
有关WebSocket和Socket的关系,可以详读:《WebSocket详解(六):刨根问底WebSocket与Socket的关系》.
WebSocket技术特征总结下就是:
WebSocket的技术原理如下图所示:
关于WebSocket API方面的知识,这里不再作讲解,可以自己查阅:https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
WebSocket兼容性良好,基本支持所有现代浏览器。
(上图来自:https://caniuse.com/mdn-api_websocket)
笔者这里采用的是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();
});
}
// ...
}
// 服务器端
var io = socketIo(httpServer);
io.on('connection', (socket) => {
socket.on('register', function(connector) {
chatRoom.onConnect(connector);
io.emit('register done');
var data = chatRoom.getDatas();
io.emit('data', { data });
});
socket.on('chat', function(message) {
chatRoom.receive(message);
var data = chatRoom.getDatas();
io.emit('data', { data });
});
});
PS:完整代码,请见本文“4、本文配套Demo和代码”一节。
响应格式如下:
随着HTML5的普及率越来越高,WebSocket的应用也越来越普及,关于WebSocket的学习资料网上很容易找到,限于篇幅本文就不深入展开这个话题。
如果想进一步深入学习WebSocket的方方面面,以下文章值得一读:
《新手快速入门:WebSocket简明教程》
《WebSocket详解(一):初步认识WebSocket技术》
《WebSocket详解(二):技术原理、代码演示和应用案例》
《WebSocket详解(三):深入WebSocket通信协议细节》
《WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)》
《WebSocket详解(五):刨根问底HTTP与WebSocket的关系(下篇)》
《WebSocket详解(六):刨根问底WebSocket与Socket的关系》
《理论联系实际:从零理解WebSocket的通信原理、协议格式、安全性》
《微信小程序中如何使用WebSocket实现长连接(含完整源码)》
《八问WebSocket协议:为你快速解答WebSocket热门疑问》
《Web端即时通讯实践干货:如何让你的WebSocket断网重连更快速?》
《WebSocket从入门到精通,半小时就够!》
《WebSocket硬核入门:200行代码,教你徒手撸一个WebSocket服务器》
《长连接网关技术专题(四):爱奇艺WebSocket实时推送网关技术实践》
短轮询、长轮询实现成本相对比较简单,适用于一些实时性要求不高的消息推送,在实时性要求高的场景下,会存在延迟以及会给服务器带来更大的压力。
SSE只能是服务器端推送消息,因此对于不需要双向通信的项目比较适用。
WebSocket目前而言实现成本相对较低,适合于双工通信,对于多人在线,要求实时性较高的项目比较实用。
学习交流:
- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》
- 开源IM框架源码:https://github.com/JackJiang2011/MobileIMSDK
本文已同步发布于“即时通讯技术圈”公众号。
同步发布链接是:http://www.52im.net/thread-3555-1-1.html
*请认真填写需求信息,我们会在24小时内与您取得联系。