HTML5介绍
1. 语义特性(Class:Semantic)
2. 本地存储特性(Class: OFFLINE & STORAGE)
3. 设备兼容特性 (Class: DEVICE ACCESS)
4. 连接特性(Class: CONNECTIVITY)
5. 网页多媒体特性(Class: MULTIMEDIA)
6. 三维、图形及特效特性(Class: 3D, Graphics & Effects)
浏览器支持:
Chrome ,IE 9 ,Firefox 8 ,Opera 11 , Safari
标签的改变:
不允许写的结束符的标签:area、basebr、col、command、 Embed、hr、img、input、keygen、link、meta、param、source、Track
可以省略结束符的标签: li、dt、dd、p、rt、optgroup、option Colgroup、thread、tbody、tr、td、th
可省略的标签:html、head、body、colgroup、tbody
html 4.01 必须声明的头文件
```html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
…………
</html>
新添加的标签:
```html 关键是看浏览器对API的支持和封装 这些标签都可以替换与交替使用
<article> 标记定义一篇文章 类似于 <p>段落 <div>无语义标签
<aside> 标记定义页面内容部分的侧边栏
<audio> 标记定义音频内容
<canvas> 标记定义图片
<command> 标记定义一个命令按钮
<datalist> 标记定义一个下拉列表
<details> 标记定义一个元素的详细内容
<dialog> 标记定义一个对话框(会话框)
<embed> 标记定义外部的可交互的内容或插件
<figure> 标记定义一组媒体内容以及它们的标题
<footer> 标记定义一个页面或一个区域的底部 和 <div> 通用。但是浏览器对footer的识别 比较专用
<header> 标记定义一个页面或一个区域的头部
<hgroup> 标记定义文件中一个区块的相关信息
<keygen> 标记定义表单里一个生成的键值
<mark> 标记定义有标记的文本
<meter> 标记定义 measurement within apredefined range
<nav> 标记定义导航链接
<output> 标记定义一些输出类型
<progress>标记定义任务的过程
<rp> 标记是用在Ruby annotations 告诉那些不支持 Ruby元素的浏览器如何去显示
<rt> 标记定义对rubyannotations的解释
<ruby> 标记定义 ruby annotations.
<section> 标记定义一个区域
<source> 标记定义媒体资源
<time> 标记定义一个日期/时间
<video> 标记定义一个视频
```
form表单新属性
```02.html
<form id="iform">
<p><label for="email">email类型:</label><input type="email" name="email" id="email" placeholder="请输入正确mail地址" /></p>
<p><label for="url">url类型:</label><input type="url" id="url" /></p>
<p><label for="date">date类型:</label><input type="date" id="date" /></p>
<p><label for="time">time类型:</label><input type="time" id="time" /></p>
<p><label for="month">month类型:</label><input type="month" id="month" /></p>
<p><label for="week">week类型:</label><input type="week" id="week" /></p>
<p><label for="number">number类型:</label><input type="number" name="number" id="number" /></p>
<p><label for="range">range类型:</label><input type="range" id="range" /></p>
<p><label for="search">search类型:</label><input type="search" results="n" id="search" value="11"/></p>
<p><label for="color">color类型:</label><input type="color" id="color" /></p>
<p><label for="placeholder">placeholder属性:</label><input type="text" id="placeholder" placeholder="点击我会以清除" /></p>
<p><label for="autofocus">autofocus属性:</label><input type="text" id="autofocus" autofocus="true"/>载入时自动获得焦点</p>
<p><label for="list">list属性:</label><input type="text" id="list" list="ilist"/>
<datalist id="ilist">
<option label="a" value="a">
<option label="b" value="b">
<option label="c" value="c">
</datalist>
</p>
<p><label for="pattern">pattern属性(正则验证):</label><input type="text" name="require2" id="pattern"
placeholder="输入邮政编码" required pattern="^[1-9]\d{5}$" /></p>
<p><label for="require">require属性:</label><input type="text" name="require" id="require" placeholder="必填项" required /></p>
<p><label for="range2">range属性:</label><input type="range" id="range2" max="100" min="1" step="20" /><span>一个滑动条效果</span></p>
<!--<p><label for="sub"></label><input type="submit" id="sub" value="提交" /></p>-->
</form>
<!--在外部提交form表单。意思就是在所有表单写完之后,只要加上一个input 标签写入 form 页面内全部的表单都可以提交-->
<input type="submit" id="sub" form="iform" value="提交" />
```
鼠标跟随和拖拽
鼠标跟随
<body>
<div id="one" style="width:100px;height:100px;background:red; position:absolute;"></div>
</body>
<script>
window.onload=function () { //页面加载完毕之后再执行
var one=document.getElementById("one"); //先获取这个 div
one.onmousedown=function () { // onmousedown 鼠标点击事件,鼠标按下。这里鼠标的三个键都可以实现
<!--注释:onmouseover 也可实现一次效果,且只能是鼠标在块内的时候实现效果,但是要反复实现,就要用move-->
document.onmousemove=function (e) { // 事件onmouseover 只要鼠标移动就触发,此时对整个页面都绑定了该事件。多用在游戏里面
one.style.left=e.clientX+"px";
one.style.top=e.clientY+"px";
}
}
}
</script>
鼠标拖拽
```html
<style>
#one{ //2.设置div样式
width:200px;height:200px;border:1px solid red;
}
#two{
width:100px;height:100px;border:1px solid blue;
}
</style>
</head>
<body>
<div id="one"> //1。先设置两个 div
</div>
<div id="two" draggable=true> // 3.2 声明这是个 draggable 可拖拽标签的元素
请拖拽我
</div>
</body>
<script>
window.onload=function () {
var one=document.getElementById("one"); //3.引入
var two=document.getElementById("two");
//拖拽区事件
two.ondragstart=function (e) { // 3.1 ondragstart 是开始拖拽的意思,拖拽物体的事件
e.dataTransfer.setData("Text","拖动完成");
one.innerHTML="开始";
}
two.ondrag=function () { //ondrag 移动物体事件
one.innerHTML+="移动";
}
two.ondragend=function () { //ondragend 结束移动物体事件
one.innerHTML+="完成";
}
昏哥线-----------------------------------------------------
//投放区事件
//注意:dragenter、dragover可能会受到默认事件的影响,所以我们在这两个事件当中使用e.preventDefault();来阻止浏览器默认事件
one.ondragenter=function (e) { //ondragenter 拖拽进去事件
one.innerHTML+="进入";
e.preventDefault();
}
one.ondragover=function (e) { //ondragover 拖拽移动事件
one.innerHTML+="移动";
e.preventDefault();
}
one.ondragleave=function (e) { //ondragleave 拖拽离开事件
one.innerHTML+="离开";
e.preventDefault();
}
one.ondrop=function (e) { //ondrop 拖拽松开鼠标事件
e.preventDefault();
alert(e.dataTransfer.getData("Text"))
one.appendChild(two); //把two对象放到one对象里面成为子对象
}
</script>
文件拖拽上传
```html
<style>
#box{
width:150px;height:150px;border:1px dashed red;
font-size:13px;line-height:150px;text-align:center;
}
</style>
</head>
<body>
<div id="box">
请拖入上传的文件
</div>
</body>
<script>
window.onload=function () {
var box=document.getElementById("box");
//拖拽对象进入区域
box.ondragenter=function (e) {
e.preventDefault()
}
//拖拽对象在区域内移动
box.ondragover=function (e) {
box.innerHTML="请松开"
e.preventDefault()
}
//拖拽对象没有在投放区,离开投放区
box.ondragleave=function (e) {
box.innerHTML="请拖入上传的文件"
e.preventDefault()
}
//拖拽对象投放在区域内
box.ondrop=function (e) {
//length 文件个数
//[0].name 文件名
//.type 文件类型
//size 文件大小 字节
//alert(e.dataTransfer.files[0].type);
var file=e.dataTransfer.files[0];
var formData=new FormData();
//aa相当于file的form表单的name
formData.append("aa",file);
var xml=new XMLHttpRequest();
xml.open("post","1.php");
xml.send(formData);
e.preventDefault()
}
}
</script>
```
多媒体
视频
因版权等问题的限制,HTML5并不是支持所有的视频格式
![](/Users/zhangduanmeng/works/buer/kejian/html5/img/geshi.jpg)
```html
<video src="movie.mp4" controls="controls"> </video> //标签中要添加 controls="controls" 否则不支持播放
<video src="movie.mp4" controls="controls">
浏览器不支持HTML5的视频播放功能,则显示格文字提示
</video>
昏哥线-----------------------------------------------------
<video width="300" controls="controls" autoplay="autoplay"> //autoplay 准备就绪之后就自动播放
<source src="movie.ogg" type="video/ogg"> //这里用两种格式是因为如果不支持前面一种,自动播放下面一种
<source src="movie.mp4" type="video/mp4"> //现在问题来了。两种都不支持,是否应该加一个备注?老湿没加
</video>
昏哥线-----------------------------------------------------
**video标签属性.png**
属性 值 描述
autoplay autoplay 如果出现该属性,视频就绪后马上播放
controls controls 向用户显示播放按钮 等 控件
height pixels 设置视频播放器的高度
width pixels 视频播放器在页面中的高度
loop loop 媒体文件播放完成再次播放
preload preload 页面加载的同时加载视频,并准备播放。如果已经用了autoplay 自动忽略该属性
poster 图片地址 显示默认图片,而不是视频的第一帧画面
src url 要播放的视频的url
昏哥线-----------------------------------------------------
**source标签属性.png**
属性 值 描述
media mediaquery 定义媒介资源的类型,供浏览器决定是否下载
src url 媒介的url
type numericvalue定义播放器在音频流中的什么位置开始播放。默认的音频从头开始播放。
属性、方法、事件供JS调用,控制播放
**videoAPI事件.png**
![](/Users/zhangduanmeng/works/buer/kejian/html5/img/videoAPI事件.png)
**videoAPI属性.png**
![](/Users/zhangduanmeng/works/buer/kejian/html5/img/videoAPI属性.png)
**videoAPI方法.png**
![](/Users/zhangduanmeng/works/buer/kejian/html5/img/videoAPI方法.png)
####音频
**yinpin.jpg**
属性、方法、事件供JS调用,控制播放,和视频基本一致
video API 事件
事件 描述
abort 当音频/视频的加载已经放弃的时候
canplay 当浏览器可以播放音频 / 视频时
canplaythrough 当浏览器可在不因缓冲而停顿的情况下进行播放时
durationchange 当音频 / 视频的时长已经更改时
emptied 当目前的播放列表为空时
ended 当前播放列表已经结束时
error 当前音频 / 视频加载期间发生错误时
loadeddata 浏览器已经加载音频 / 视频的当前帧
loadedmetadata 浏览器已加载音频 / 视频的元数据时
loadstart 当浏览器开始查找音频 / 视频时
pause 当音频 / 视频 暂停时
play 开始或不再暂停时
playing 因缓冲暂停或停止后,已经就绪时
progress 正在下载音频 / 视频时
ratechange 播放速度更改时
seeked 用户已移动 / 跳跃到音频 / 视频中的新位置时
seeking 用户开始移动。跳跃到新的播放时长位置时触发
stalled 当浏览器尝试获取媒体数据,但数据不可用时
suspend 当浏览器可以不获取媒体数据时
timeupdate 当目前播放位置已更改时
volumechange 当音量已经更改时
waiting 当视频由于需要缓冲下一帧而停止
小例子
```html
<body>
<video controls=controls loop =loop poster="fbi.png" id="video">
<source src="FBI.mp4"></source>
<source src="FBI.webm"></source>
</video>
<input type="button" value="播放" id="play"/>
<audio src="fcml.mp3" controls=controls id="vd"> 这句话是莫名其妙的乱入的 </audio>
</body>
<script>
var playbtn=document.getElementById("play");
var video=document.getElementById("video");
playbtn.onclick=function () {
video.play();
}
var play = document.getElementById("play");
var vd = document.getElmentById("vd");
play.onclick = function(){
vd.play();
if(vd.paused){
vd.play();
play.value = 'paused now';
}else{
vd.pause();
play.value = 'play again';
}
</script>
```
地理位置定位
使得开发人员不用借助其他软件就能轻松实现位置查找,地图应用,导航等功能,具有划时代的意义!
地理位置定位基本原理
GPS、WIFI、IP、手机信号基站
核心对象
Geolocation (几狼ak神)是 window.navigator 下面的一个子对象,该对象提供了实现地理位置定位的接口。
要用该功能首先判断浏览器是否支持 navigator.geolocation该对象。
navigator.geolocation.getCurrentPosition(success,error,options)
**success(position) 获取信息成功的回调函数**
对象:
coords.latitude(纬度)
coords.longitude(经度)
coords.altitude(海拔)
coords.accuracy(位置精确度)
coords.altitudeAccuracy(海拔精确度)
coords.heading(朝向,这个一般是手机才有,以正北方为准)
coords.speed (速度)
timestamp(响应的日期/时间)
**error(errorcode)获取信息失败的回调函数**
code是错误代码
message是错误信息。
**options获取信息前可以按照你的需求来设置一些参数{对象}**
enableHighAccuracy 表示是否允许使用高精度,
timeout指定超时时间
maximumAge 是指缓存的时间
#前方注意参数
**geolocation 还有两个方法:**
1.watchPosition(success,error,options) 表示重复获取地理位置,可以设置多长的时间,
相当于将getCurrentPosition这个方法利用setinterval不断执行,其他用法和参数使用一样。
2.clearWatch()用来清除前一次获取的位置信息。这个两个方法配合使用,能够实现一些很棒的功能,比如说:导航等!
```html
<body>
<div id="map">
</div>
</body>
<script type="text/javascript">
if (navigator.geolocation){ //先判断浏览器是否支持该功能,success成功时的回调;error失败时的回调;options参数设置(对象)
navigator.geolocation.watchPosition(success,error,options);
}else{
alert("浏览器不支持地理定位。");
}
function success(ev){
alert(ev.coords.latitude+'----'+ev.coords.longitude);
}
function error(err){
alert(err.code+'----'+err.message);
}
var options = {};
</script>
昏哥线--------------------------------------------------------------------------------------
<script type="text/javascript">
if (navigator.geolocation){ //先判断浏览器是否支持该功能,success成功时的回调;error失败时的回调;options参数设置(对象)
navigator.geolocation.watchPosition(success,error,options);
}else{
alert("浏览器不支持地理定位。");
}
function success(ev){
var map = document.getElementById("map");
map.innerHTML = "您所在维度是: "+ev.coords.latitude + ";<br>您所在的经度是: "+ev.coords.longitude; // 请求成功,弹出内容
map.innerHTML = "您所在方向是: "+ev.coords.headeing;
map.innerHTML = "您所移动的速度是: "+ev.coords.speed;
map.innerHTML = "您所在海拔是: "+ev.coords.altitude;
}
function error(ev){
alert(ev.code+'----'+ev.message);
}
var options = {};
</script>
```
简单本地存储
HTML5 提供了四种在客户端存储数据的新方法,即localStorage、sessionStorage 这两个是像 KEY VALUE 键值对的存放形式,
存储形式单一,但查询方便,优于Websql Database. globalStorage、
WebSql Database 最后这个是关系型数据库,适用于存储大型的,复杂的数据;
简单存储与cookie的区别:
web存储安全性较高,在数据量上可以达到5M,而cookie最多也就4KB,或者20个key/value对。
```html
<body>
<script>
document.cookie="name=zhangsan";//关闭浏览器重新打开则消失
alert(document.cookie);
localStorage.setItem("name","lisi");//关闭浏览器重新打开不会消失
alert(localStorage.getItem("name"));
sessionStorage.setItem("name","wangwu");//关闭浏览器重新打开则消失
alert(sessionStorage.getItem("name"))
</script>
</body>
```
localStorage/sessionStorage都有相同的Api如:
localStorage.length 获得storage中的个数
localStorage .key(n) 获得storage中第n个键值对的键
localStorage.key = value
localStorage.setItem(key, value) 添加
localStorage.getItem(key)获取
localStorage.removeItem(key) 移除
localStorage.clear() 清除
```html
记住用户名和密码
<script>
window.onload=function () { //下面先分别获取用户名,密码,是否记住密码的id
var names=document.getElementsByName("names")[0];
var pass=document.getElementsByName("pass")[0];
var save=document.getElementsByName("save")[0];
if(localStorage.getItem("names")&&localStorage.getItem("pass")){ //如果这两个都有值
names.value=localStorage.getItem("names");
pass.value=localStorage.getItem("pass");
save.checked=true; //假设存在,那么三个都存在,都有
}
save.onclick=function () {
if(save.checked){
//alert(name.value); 可以先测试是否有值
localStorage.setItem("names",names.value);
localStorage.setItem("pass",pass.value);
}else{
localStorage.removeItem("names");
localStorage.removeItem("pass");
}
}
}
</script>
</head>
<body>
用户名:<input type ="text" name="names"><br/>
密码:<input type="password" name="pass"><br/>
是否永久保存<input type="checkbox" name="save">
</body>
```
WebSql Database
三个核心方法
openDatabase:这个方法使用现有数据库或创建新数据库创建数据库对象。
transaction:这个方法允许我们根据情况控制事务提交或回滚。
executeSql:这个方法用于执行真实的SQL查询。
```html
<body>
<script>
window.onload=function () {
var one=document.getElementById("one");
if(window.openDatabase){ //要先测试是否支持database
//openDatabase参数说明:
//数据库名称;版本号,目前为1.0;对数据库的描述;设置数据的大小(字节);回调函数(可省略)
var dataBase = openDatabase("student", "1.0", "学生表", 1024 * 1024, function(){});
dataBase.transaction(function (fx) { // transaction 创建一个表
// fx.executeSql(
// "create table if not exists stu (id REAL UNIQUE, name TEXT)", //REAL UNIQUE 主键唯一
// [],
// function () {
// alert("表创建成功");
// },
// function () {
// alert("创建表失败");
// }
// );
// fx.executeSql( // 插入数据
// "insert into stu (id ,name) values(?,?)", //?是占位符。防止sql注入
// [1,"张三"],
// function () {
// alert("数据插入成功");
// },
// function () {
// alert("数据插入失败");
// }
// );
// //更新数据
// fx.executeSql(
// "update stu set name=? where id=?",
// ["李四",1],
// function () {
// alert("数据更新成功");
// },
// function () {
// alert("数据更新失败");
// }
// );
//查询数据
// fx.executeSql(
// "select * from stu",
// [],
// function (fx,result) {
// for (var i=0; i<result.rows.length; i++) {
// one.innerHTML+=result.rows.item (i)["name"];
// }
// alert("数据查询成功")
// },
// function () {
// alert("数据查询失败");
// }
// );
//删除数据
// fx.executeSql(
// "delete from stu where id=?",
// [1],
// function () {
// one.innerHTML="";
// alert("数据删除成功");
// },
// function () {
// alert("删除失败");
// }
// );
// //删除表
// fx.executeSql(
// "drop table stu",
// [],
// function () {
// alert("表删除成功");
// },
// function () {
// alert("表删除失败");
// }
// );
});
}else{
alert('no');
}
}
</script>
<div id="one">
</div>
</body>
```
离线缓存
一个离线网络应用程序就是一个URL的列表——HTML,CSS,JavaScript,图片,或者其他类型的资源。
把这些资源,在本地缓存下来,当你尝试在没有网络连接时访问网络应用程序,你的网络浏览器将自动切换并使用本地代替。
1、服务器端配置:
需要在 WAMPP 或 XAMPP 的 apache 配置文件 http.conf(搜索AddType,加到下面)
加:AddType text/cache-manifest .manifest //注意,这里点前面有个空格
创建这个 buer.manifest 清单文件:
CACHE MANIFEST
\# 这一句必须存在,而且必须放在头部
CACHE
\#这一句指明要缓存的内容
NETWORK
\#声明用于指定无需缓存的文件
FALLBACK
\#这个声明允 许你在资源不可用的情况下,将用户重定向到特定文件
\#(当更新文件不成功是,默认使用原来的文件)
昏哥线-------------------------------------------------------------------------------------------------
//1.创建一个名为 buer.manifest 的文件
buer.manifest:
//第一句写入
CACHE MANIFEST
#### v1.0
CACHE:
1.html
1.css
1.js
NETWORK:
1.jpg
FALLBACK:
昏哥线-------------------------------------------------------------------------------------------------
2、关联 manifest 文件到 html 文档 :
```html <html manifest="/buer.manifest"> ```
1.html
```html
<!DOCTYPE html>
####<html manifest="buer.manifest"> //注意,这里要加上 manifest="文件名"
<head>
<title>noTitle</title>
<meta charset="">
<link rel="stylesheet" href="1.css">
</head>
<body>
<div class="one">
布尔教育,西岭最帅
</div>
<img src="1.jpg">
</body>
<script src="1.js"></script>
</html>
```
昏哥线-------------------------------------------------------------------------------------------------
创建1.js 内容如下
```js
var div=document.getElementsByTagName("div")[0];
div.onclick=function () {
alert("是的,很帅!!");
}
```
昏哥线-------------------------------------------------------------------------------------------------
创建1.css 内容如下
```css
.one{
width:200px;height:200px;;border:1px solid red;
}
```
昏哥线-------------------------------------------------------------------------------------------------
重新联网后,HTML内容改变,但是页面显示没有变,因为默认优先使用缓存,要想修改网页内容有两个办法:
修改 html 内容后
1.清空缓存,再次登陆页面。
2.修改 xxx.manifest 文件内 CACHE MANIFEST 下面#### v1.0, 改为 v1.1 ,再刷新;
昏哥线-------------------------------------------------------------------------------------------------
HTML5 提供了两种检测是否在线的方式:
navigator.onLine 和 online/offline 事件。
1. navigator.onLine 属性表示当前是否在线。如果为 true,表示在线;如果为 false, 表示离线
2. 开发者还需要在网络状态发生变化时立刻得到通知,因此 HTML5 还提供了 online/offline 事件
applicationCache属性、事件、方法API,但是,没有浏览器实现;
Canvas 这玩意儿可以做3D游戏?主要是给页面游戏开发用的
```html
<!DOCTYPE html>
<head>
<meta charset=utf-8>
<title>PHP100 HTML5视频教程-canvas</title>
</head>
<body>
<canvas id="cv" width="500" height="500" onmousemove="mousexy(event)"></canvas>
<div id="ds"></div>
<script type="text/javascript">
//叠加色块
var c=document.getElementById("cv"); // 1.首先获取canvas
var cv=c.getContext("2d"); // 2.声明创建一个名为 2d 的画布
cv.fillStyle="#FF0000"; // 3.定义颜色 这里必须要用16进制来写
cv.fillRect(0,0,300,300); // 3.1 定义矩形的大小,第一个0 是html默认的左上角 第二个0 是右下角
cv.fillStyle="rgba(0,0,255,0.5)"; // 3.2 定义颜色,最后一个0.5 表示透明度为多少,0.5就是半透明
cv.fillRect(200,200,500,500); // 3.3 定义第二个矩形大小
//========线======
cv.moveTo(10,10); //1. 起始位置的坐标
cv.lineTo(150,50); //2. 终止位置 两个点确定一条线
cv.lineTo(10,50); //2.1 如果没有再次设置起始位置将从结束位置开始画
cv.lineTo(10,10); //2.2 如果再画这条线,就连起来了,成了三角形
cv.stroke(); //3. 结束图形
//=======圆=======
cv.fillStyle="blue"; //定义演示
cv.beginPath(); //从新开始画,防止冲突重叠
cv.arc(200,200,30,0,Math.PI*2,true); //x坐标,y坐标,半径,Math.PI是圆周率
cv.closePath(); //结束画布,防止冲突重叠
cv.fill(); //结束渲染
//======颜色渐变====
var grd=cv.createLinearGradient(100,100,175,50); //颜色渐变的起始坐标和终点坐标
grd.addColorStop(0,"yellow"); //0表示起点..0.1 0.2 ...1表示终点,配置颜色
grd.addColorStop(1,"blue");
cv.fillStyle=grd; //生成的颜色块赋值给样式
cv.fillRect(100,100,175,50); //设置色块
//=======图形载入=====
var img=new Image()
img.src="logo.png"
cv.drawImage(img,220,30);
//监视鼠标
function mousexy(n)
{
x=n.clientX;
y=n.clientY;
document.getElementById("ds").innerHTML="坐标: x轴"+x+" y轴"+y;
}
</script>
</body>
</html>
```
websocket
Websocket只是一个网络通信协议
就像 http、ftp等都是网络通信的协议;不要多想;
相对于HTTP这种非持久的协议来说,Websocket是一个持久化网络通信的协议;
####WebSocket和HTTP的关系
WebSocket和HTTP的关系
有交集,但是并不是全部。
![](/Users/zhangduanmeng/works/buer/kejian/html5/img/websocket+http.png
)
Websocket只是借用了HTTP的一部分协议来完成一次握手。(HTTP的三次握手,此处只完成一次)
昏哥线-------------------------------------------------------------------------------------------------
http和websocket 请求头对比:
http请求头:
Accept:text/html,application/xhtml-xml,application/xml;q=0.9,*/*q=0.8
Accept-Endcoding gzip,deflate
Accept-Language zh-CN,zh:Q=0.8,en-US;Q=0.5,en;Q=0.3
Connection keep-alive
Host localhost
If-Modified-Since Mon,29 Feb 2016 4:03:01 GMT
If-None-Match "abc-52ce168531ffc"
Referer http://localhostlH5
User-Agent Mozilla/5.0 (window Nt 6.1)
而 websocket 请求头中,
Connection keep-alive Upgrade 多了 Upgrade 升级的信息
Sec-WebSocket-Version 13 表示这是第13个升级的版本
昏哥线-------------------------------------------------------------------------------------------------
HTTP:
原来的时候,客户端通过http(骑马)带着信请求服务器,服务器处理请求(写回信),再次通过http(骑马)返回;链接断开;
WebSocket:
客户端通过http(骑马)带着信请求服务器,但同时,携带了Upgrade:websocket和Connection:Upgrade(两根管子),
服务器如果支持WebSocket协议(有两根管子的接口),使用Websocket协议返回可用信息(丢弃马匹),
此后信息的传递,均使用这两个管子,除非有一方人为的将管子切断;若服务器不支持,客户端请求链接失败,返回错误信息;
http和websocket 响应头对比:
![](/Users/zhangduanmeng/works/buer/kejian/html5/img/http响应头.jpg
)
![](/Users/zhangduanmeng/works/buer/kejian/html5/img/websocket响应头.jpg
)
####websocket和ajax轮询、long poll的区别
首先是 ajax轮询 ,ajax轮询的原理非常简单,让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息
long poll 其实原理跟 ajax轮询 差不多,都是采用轮询的方式,不在论述;
从上面可以看出,轮询其实就是在不断地建立HTTP连接,然后等待服务端处理,可以体现HTTP协议的另外一个特点,**被动性**。
同时,http的每一次请求与响应结束后,服务器将客户端信息全部丢弃,下次请求,必须携带身份信息(cookie),**无状态性**;
**Websocket的出现,干净利落的解决了这些问题;**
所以上面的情景可以做如下修改。
客户端:啦啦啦,我要建立Websocket协议,需要的服务:chat,Websocket协议版本:17(HTTP Request)
服务端:ok,确认,已升级为Websocket协议(HTTP Protocols Switched)
客户端:麻烦你有信息的时候推送给我噢。。
服务端:ok,有的时候会告诉你的。
很遗憾:Nginx和Apache 不支持WebSocket协议!
Swoole 韩天峰 开发的 Perl语言也是他参与开发的
但是,为了用PHP配合HTML5完成一次WebSocket请求和响应,哥走过千山万水,在密林深处,发现了Swoole : [http://www.swoole.com/](http://www.swoole.com/);
PHP语言的异步、并行、高性能网络通信框架,使用纯C语言编写,提供了PHP语言的异步多线程服务器,
异步TCP/UDP网络客户端,异步MySQL,数据库连接池,AsyncTask,消息队列,毫秒定时器,异步文件读写,异步DNS查询。
**支持的服务:**
HttpServer
WebSocket Server
TCP Server
TCP Client
Async-IO(异步)
Task(定时任务)
**环境依赖:**
仅支持Linux,FreeBSD,MacOS,3类操作系统
Linux内核版本2.3.32以上
PHP5.3.10以上版本
gcc4.4以上版本或者clang
cmake2.4+,编译为libswoole.so作为C/C++库时需要使用cmake
**安装:**
必须保证系统中有以下这些软件:
php-5.3.10 或更高版本
gcc-4.4 或更高版本
make
autoconf
> Swoole是作为PHP扩展来运行的
安装(root权限):
cd swoole
phpize
./configure
make
sudo make install
配置php.ini
extension=swoole.so
> 想研究Swoole的同学,自己去看手册(虽然写的不好,但是还是能看懂的)
**做一个聊天室**
服务器端:socket.php
```php
//创建websocket服务器对象,监听0.0.0.0:9502端口
$ws = new swoole_websocket_server("0.0.0.0", 9502);
//监听WebSocket连接打开事件
$ws->on('open', function ($ws, $request) {
$fd[] = $request->fd;
$GLOBALS['fd'][] = $fd;
//$ws->push($request->fd, "hello, welcome\n");
});
//监听WebSocket消息事件
$ws->on('message', function ($ws, $frame) {
$msg = 'from'.$frame->fd.":{$frame->data}\n";
//var_dump($GLOBALS['fd']);
//exit;
foreach($GLOBALS['fd'] as $aa){
foreach($aa as $i){
$ws->push($i,$msg);
}
}
// $ws->push($frame->fd, "server: {$frame->data}");
// $ws->push($frame->fd, "server: {$frame->data}");
});
//监听WebSocket连接关闭事件
$ws->on('close', function ($ws, $fd) {
echo "client-{$fd} is closed\n";
});
$ws->start();
```
客户端:Socket.html
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="msg"></div>
<input type="text" id="text">
<input type="submit" value="发送数据" onclick="song()">
</body>
<script>
var msg = document.getElementById("msg");
var wsServer = 'ws://192.168.1.253:9502';
//调用websocket对象建立连接:
//参数:ws/wss(加密)://ip:port (字符串)
var websocket = new WebSocket(wsServer);
//onopen监听连接打开
websocket.onopen = function (evt) {
//websocket.readyState 属性:
/*
CONNECTING 0 The connection is not yet open.
OPEN 1 The connection is open and ready to communicate.
CLOSING 2 The connection is in the process of closing.
CLOSED 3 The connection is closed or couldn't be opened.
*/
msg.innerHTML = websocket.readyState;
};
function song(){
var text = document.getElementById('text').value;
document.getElementById('text').value = '';
//向服务器发送数据
websocket.send(text);
}
//监听连接关闭
// websocket.onclose = function (evt) {
// console.log("Disconnected");
// };
//onmessage 监听服务器数据推送
websocket.onmessage = function (evt) {
msg.innerHTML += evt.data +'<br>';
// console.log('Retrieved data from server: ' + evt.data);
};
//监听连接错误信息
// websocket.onerror = function (evt, e) {
// console.log('Error occured: ' + evt.data);
// };
</script>
</html>
```
websocket API 手册:
[https://developer.mozilla.org/en-US/docs/Web/API/WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)