疯狂的html css,疯狂Html+CSS+JS 中JS总结

0 总结

本书的JS

第一章有讲语法有挺多常见的坑点和原理解释很不错

第二章DOM编程讲述了挺多API

第三章事件处理机制其实对事件中的this关键字和事件传播顺序讲4. 解还不错

第四章WebStorage本地存储例子鲜明

第五章Worker应付复杂的js操作

第六章客户端通信WebSocket挺有用,可以实现用户与用户在浏览器中互动

1. JavaScript语法

1.1 执行js代码

javascript:alert(‘执行js’);//一般放在超链接中,用户点击即执行,

1.2 变量赋值

var a = 1;//显式

a =1; //隐式

1.3 全局变量与局部变量

...

var scope = "全局变量";

function test(){

alert(scope); // undefiend

var scope = "局部变量";

alert(scope); // 局部变量

}

因为全局变量被局部变量覆盖了.虽然局部变量的scope还没赋值,但是已经在方法里”占”上位置了.

但如果把局部变量的var删了,就会先输出全局变量后输出局部变量,因为没有var在方法里给局部变量”占”位置;

1.4 浮点数

var a =.333

var b = a * 5;

alert(b);

得出的结果是 1.66499999999999999

所以在js中判断浮点数是否相等 建议判断两者的差值是否小于一个足够的数(例如0.0000000000001)

1.5 字符串

js中没有字符类型变量 “”与’‘一致

var s ="abcdefg"

//b = "def"

b = s.slice(3, -1);

1.6 字符串的正则表达式方法中

match()返回匹配的字符串(数组或null),可加/g进行全局匹配多个

search()返回匹配的索引值 单个

1.7 undefined和null

null == undefined //true

null === undefined //false

undefined 是没设值

null则是设定了为null值

1.8 运算符

//逗号运算符 取最右返回值

a = (b =5 , c = 7 , d =56) //a =56

a = void(b =5 , c = 7 , d =56) //a = undefined

1.9 typeof和instanceof

typeof 用来获得 实例类型 :

typeof("123"); //string

instanceof 判断变量是否为某类的实例

var a = [4,5];

alert(a instanceof Array); //true

1.10 语句

抛出异常

throw new Error("用户自定义异常"); //一般用于终止程序和返回错误提示是个不错的选择;

try{

}catch(e){

alert(e.message); // "用户自定义异常"

}

for in

//这回输出浏览器的所有属性,做浏览器兼容之前可以考虑看看.

for( prop_name in navigator){

document.wrti(prop_name + " : " + navigator[propname]);

}

跳出命名for

outer:

for(...){

for(...){

...

continue outer;

}

}

1.11 函数

js 允许先调用函数 再定义函数

1.11.1 定义匿名函数

var show_name = function(name){

alert(name);

}

show_name("K"); //K

这样的好处是什么,如果直接定义function 它实际上也是创建了一个对象

1.11.2 函数既对象

var hello = function(){...};

hello instanceof Function //true;

hello instanceof Object //true;

alert(heelo) //输出函数源代码

1.11.3 调用函数方式的不同

直接调用函数 返回return的值或void

new 函数 得到的都是对象 - -…….

1.11.4 this关键字.

在函数中使用this.变量 该变量就是函数的实例变量,而非局部变量,无论它在哪里.

函数可依附在类中.如没指定 则依附在winodw对象中

var hello =function(){...}

window.hello();

var p = {

wark: function(){...}

}

p.wark();

1.11.5 函数中的变量有三种

function Person(){

//局部变量 只能在函数里访问

var id ;

//实例属性 通过对象.访问

this.age ;

//类属性 通过Patient.name访问 与static类似

Person.name ;

}

1.11.6 js是一种动态语言,能随时给对象增加属性和方法

function Student(){ };

var student =new Student();

//动态增加name属性

student.name = 'K';

alert(sutdent.name) //K

Student.age =22 ;

alert(Student.age); //22 类属性也是可以动态添加的

1.11.7 调用函数的三种方式

直接调用

windows.alert();

//or

alert();

call()调用

作用:动态地传入一个函数引用

var each = function(array,fn){

for(var index in arrary){

//null表示以window为调用者fn函数

fn.call(null,index,arrary[index]);

}

}

each([4,20,3] , function(index ,ele){

alert("第 " + index "个元素是 : " + ele);

});

call()调用函数语法为:函数引用.call(调用者,参数1,参数2...)

直接调用函数语法为:调用者.函数(参数1,参数2 ...) = 函数.call(调用者,参数1,参数2 ...)

apply()调用

apply和()call()基本相似,区别如下:

通过call()调用函数时,括号必须详细列出每个参数

通过apply()动态地调用函数时,可以在括号中以arguments来代表所有参数

var myfun = function (a , b){

alert(a + " " +b);

}

myfun.call(window ,12 ,23); //12 23;

myfun.apply(window ,[20 , 39]); //20 39

var example = function (num1 ,num2){

//直接调用arguments代表调用者(example,this代表example)时的传入的所有参数

myfun.apply(this,arguments);

}

example(20,40) //20 40

1.11.8 函数的独立性

在函数A中可以定义函数B,但是函数B还是独立于函数A

function Person(name){

this.name = name;

this.info = function(){

alert(this.name);

}

}

var person =new Person('K');

person.info(); //K

var name = 'K_window';

//由于window为调用者 ,this.name访问的是window.name

p.info.call(window); //K_window

来爽一发猫学狗叫?.

function Dog(name,bark){

this.name = name;

this.bark = bark;

this.info =function(){

alert(this.name + " " + this.bark);

}

}

function Cat(name){

this.name =name;

}

var dog = new Dog("K","汪汪!");

var cat = new Cat("K_2");

dog.info.call(cat); //K_2 undefined

1.11.9 参数传递方式

和JAVA一样 都是值传递拉~.

基本类型

function change(arg){

arg =10 ;

alert(arg);

}

var x = 5;

alert(x); //5

change(x); //10

alert(x); //5

复合类型

function change(person){

person.age = 10;

alert(person.age);

person = null;

}

var person = {age : 5};

alert(person.age); //5

change(person); //10

alert(person.age); // 10

alert(person); // []object Object]

复合类型的传递为值传递,原person和参数person指向同一javascript对象,所以当改变age的时候,是在改变javascript对象的age,但是参数person赋值为null,原person并无改变.

1.11.10 空参数

function text(person){

alert( typeof parson);

}

text(); //undefined

所以对于弱类型,方法重载是无作用的,因为js会把空参数当做undefined传递进去;

同名函数,后面出现的会覆盖前面的,无论参数个数是多少.

1.11.11 对象和关联数组

javascript和Map有点类似,当key为对象,value为函数,该该函数就是对象的方法,当key为对象,value为基本类型,则该基本类型为对象的属性.(以上为便于理解,切勿细琢)所以访问属性时,可以obj.propName也可以obj[propName].

但有时候我们只能用obj[propName],因为.propName不能把propName当做变量处理,而是把他当成’propName’字符串

function Person(name){

this.name =name;

this.info = function(){

alert(K);

}

}

var person = new Person("K");

//遍历person属性

for (propName in person){

alert(p[propName]);//alet K info源代码 假如此处用p.propName则undefined,因为Person无'propName'变量.

}

1.11.12 继承和prototype

在一个类(函数)中定义一个函数会导致

性能低下:每次new一个类 都会生成一个函数

函数中若引用类的局部变量会产生闭包 导致局部变量一直存在

function Person(){

var local = "局部变量"

this.info = function(){

//产生闭包

alert(local);

}

}

var person = new Person();

person.ifno(); // 局部变量

解决方案:prototype

增加了prototype属性的类可视为继承了原先的类(伪继承)

function Person(){...}

var person = new Person();

//person.wark(); 程序报错wark不存在

Person.prototype.wark = function(){...}

person.wark(); //ok

在prototype之前实例化的类会具有wark方法吗? 有的,因为prototype这样并不会产生一个新的类,而是直接动态的往Person里加函数.

判断某方法是否继承了该对象

该对象.prototype['某方法'] != undefined;

var test = new 该对象();

test.某方法 !=undefined ;

1.12 创建对象三种方式

//(单身汪别说我不教你)

new关键字调用构造器创建对象

function Person(name){...}

var person_1 = new Person();

var person_2 = new Person('K'); //js不存在方法重载,空参数undefined顶替

使用Object直接创建对象

var my_obj = new Object();

my_ojb.name = 'K';

my_obj.handsome = function(){...}

function text(){...}

my_obj.text = text;//不要添加(),不然会认为是调用方法

JSON创建对象

ver person = {

name : 'K',

school : ['ChangAn','TianJin'],

girl_friends :[

{

name : 'Haski',

age : 11

},

{

name : 'Samoyed',

age : '8'

}

]

}

alert(person.girl_friends[0].name); //Haski

2 DOM编程

DOM操作其实JQuery已经做得很好了,这里简单补充一下原生JS的知识

HTML文档中只有一个根节点

2.1 访问HTML元素

id getElementById(‘id’); or getElementsByName(‘name’);

根据节点关系

Node parentNode: 返回父节点

Node previousSibling: 返回前一个兄弟节点

Node nextSibling: 饭后后一个兄弟节点

Node[] childNodes 返回当前节点的所有节点

Node[] getElementsByTagName('标签名称'): 返回当前节点具有制定标签的子节点

//注意ol标签的子标签IE8和其他浏览器不一样(其他浏览器会把ol下的li和其后面的空白分别当成2个节点,IE8则不会)

2.2 增加HTML函数

document.createElement(“标签名”);

复制节点 var node =ul.firstChild.nextSibling.cloneNode(boolean),boolean为true时,复制所有所有后代节点.false则仅复制当前节点.clone了节点以后还要找一个节点添加进去.

2.3 添加节点

appendChild(Node);添加为当前节点的最后一个子节点

inserBefore(newNode,refNode);在refNode前添加newNode

replaceChild(newChild,oldChild);替换节点

增加select选项 new Option(text,value,defaultSelected,selected);

2.4 删除节点

removeChild(oldNode);

2.5 window对象

返回上一个页面: back()

window.href: 当前url

window.width: 屏幕横向分辨率

window.height: 屏幕纵向分辨率

遍历window.screen,包含所以屏幕属性

for(var propName in window.screen){

alert(propName+":" +screent[propname]);

}

cofrim(‘标题’); 能弹出是否确认的提示框

prompt(‘标题’); 能弹出一个文本输入框输入.

定时器:setInterVal,clearInterval()

var timer;

var cur = new Date().getTime();

var setTime = function(){

document.getElementById("tm").innerHTML = new Date().toLocationString();

if(new Date().getTime- cur > 60 *1000){

clearInterval(timer);

}

}

//每1S执行一次,执行了60次就暂停

timer = window.setInterval("setTime()",1000);

2.6 navigator和地理位置

navigator汉堡浏览器所有信息,遍历循环获取信息

for(var propName in window.navigator){

alert(propName + ":" + window.navigator[propName]);

}

HTML5新增geolocation属性

Geolocation提供的方法

getCurrentPosition(onSuccess,onError,options)

int watchCurrentPostion(OnSuccess,onError,options),周期性调用getCurrentPosition,返回的int代表这个”监听器”的ID,用来clearWatch(watchID)取消监听

clearWatch(watchID),用于取消watchCurrentPosition

上面的前两个方法的options参数是一个对象,可包含3个变量

enabelHighAccuracy(是否制定高精度地理位置)

tiemout 设置超时时长

maximumAge,设置缓存时间

例子:

var geoHandler = function(position){

var geoMsg = "用户地址位置是 :
"

geoMsg += "timestamp属性为 :" + position.timestamp + "
"//获取位置的时间

var cords =position.coords;

for(var prop in coords ){

geoMsg += prop + ": " + coords[prop] +"
"//经纬度,移动速度等

}

document.writeln(geoMsg);

}

var errorHandler = function(error){

var errMsg = {

1: '用户拒绝了位置服务'

2: '无法获取地址位置信息'

3: '获取地理位置信息超时'

};

alert(error[error.code]);

}

navigator.geolocation.getCurrentPosition(geoHandler

, errorHandler

, {

enableHighAccuracy:true,

maximuAge:1000

});

2.7 HTML5新增浏览器分析

实现该功能主要通过performance对象

其中的(PerformanceTiming)timing属性包含加载时间相关的属性

另外(PerformanceNavigation)navigation,主要属性有

type :

TYPE_NAVIGATE(数值为0): 超链接/输入url

TYPE_RELOAD(1): 重新加载方式,diaoyonglocation.reload()等

TYPE_BACK_FORWARD(2): 通过浏览器的前进方式

TYPE_RESERVED(255): 未知方式

3 事件处理机制

3.1 常见事件

onabort: 图片加载终端

onblur: 失去焦点

onchange: 表单域更改

onclick: 点击

onerror: 图片加载出错

onfocus: 获得焦点

onkeydown: 按下鼠标

onkeypress: 当焦点在当前元素上,单击键盘某个键触发

onkeyup: 当焦点在当前元素上,松开某个键触发

onload: 某个对象加载完毕,适用于img,oframe,body

onunload: 当某个对象从窗口下卸载触发,适用于img,oframe,body

onmousedown: 焦点停留在当前元素上,按下鼠标触发

onmousemore: 当焦点在当前元素上,鼠标移动到该元素

onmouseout: 鼠标移出当前元素触发

onmouseover: 鼠标移动到该元素触发

onmouseup: 焦点在当前元素,松开鼠标时触发

onreset: 重置表单时触发

onsubmit: 表单提交触发

3.2 事件处理和this

p.info = function(){

alert(this.name);

}

document.getElementById("bt").onclick = p.info//this指向'bt'控件

document.getElementById("bt").onclick = new function (){ p.info();} //this总是指向p

注意表单设置id为x和name为y时候,相当于表单创建了x属性和y属性,所以id和name不能是关键字submit等

3.3 DOM

创建监听事件

objectTarget.addEventListener(“eventType”,handler,capture),第一个参数表示绑定的事件,如click、keypress之类的,第二个制定绑定的函数,第3个位boolean,true表示监听捕获阶段,false表示监听冒泡阶段

objectTarget.removeEventListener(“eventType”,handler,captureFlag): 删除绑定事件

捕获状态阶段的绑定事件先执行,事件冒泡状态阶段的绑定事件后执行. 捕获状态阶段从外往内触发,事件冒泡状态阶段从内往外触发.

绑定例子

var got_click = function (event){

for ( event_one in event){

alert(event_one + " : " + event[event_one]);

}

}

document.getElementByID("test").addEventListener("cilck",got_click,true);

阻止事件传播

event.stopPropagation();

取消事件的默认行为,如跳转页面等,但不会阻止事件传播.

event.preventDefault();

3.3.1转发事件

DOM提供了dispathEvent方法用于事件转发,该方法属于Node

target.dispathEvent(Event event),将event转发到target上

DOM的dispath()必须转发人工合成的Event事件

document.createEvent(String type),tpy参数用于指定事件类型,eg:普通事件Events,UI事件UIEvents,鼠标事件:MouseEvents

初始化事件

initEvent(具体参数...)

initUIEvent(具体参数...)

intMouseEvent(具体参数...)

//例子

...

var rd =function(evt){

alert("事件冒泡阶段: " + evt.currentTarget.value +"被点击了");

var e =document.createEvent("Evnets");

e.initEvent("click",true,false);//true表示是否支持冒泡,false表示是否有默认行为

document.getElementById("bn2").dispathEvent(e);

}

var go_click = function (evt){

alert("事件冒泡阶段: " + evt.currentTarget.value);

}

document.getElementById("bn1").addEventListener("click",rd,false);

document.getElementById("bn2").addEventListener("click",go_click,false);;

//点解按钮一结果

alert(事件冒泡阶段: 按钮一被点击了);

alert(事件冒泡阶段:按钮2);

点击按钮1,按钮执行了前面按钮一被点击了提示语句后,将点击事件转给了按钮2,按钮2执行自身的点击事件.

4 本地存储与离线应用

4.1 Web Storage

使用理由之一Cookie的局限性:

Cookie大小被限制为4KB

Cookie会包含在每次HTTP请求中

Cookie网络传输未加密(除非整个应用都使用SSL)

Web Storage分两种

Session Storage: 生命周期与用户Session一致(用户Session是指:用户从访问网址到离开网址/关闭浏览器)

Local Storage: 保存在用户的磁盘中,失效的方式为用户/程序显示删除.

Web Storage的方法有

length: 返回key-value对数

key(index): 返回第index个key

getItem(key): 获取key对应的value

set(key,value): 设置key-value

removeItem(key): 删除key-value

clear(): 清除所有key-value

Web Storage包含在window对象中

当value为对象时,建议用JSON存储

4.2 构建离线应用

在html标签中修改

//表明该页使用index.manifest文件

index.mainfest文件

CACHE MANIFEST

//第一行必须为上述字符

//指定版本号

#version 1

//本地缓存资源

CACHE

inedx.html

logo.jpg

//不缓存的资源

NETWORK

*

//前者表示在线状态使用的资源,后者代表离线状态使用的资源

FALLBACK

test.js offline.js

Tomcat为例,天津映射文件

manifest

text/cache-mainfest

启动应用后,页面可刷新(即使离线状态),并使用离线时候的资源

4.2.1 判断在线状态

navigator.onLine属性: true表示在线

online/offline事件: 当在线/离线状态切换时,body上的online/offine事件会被触发,沿着document.body、document和window冒泡

window.addEventListener("offline",function(){

alert("离线状态")

},true);

if(navigator.onLine){

alert("在线");

}

4.2.2 applicationCache对象

js可通过applicationCache控制离线缓存.

status属性:

UNCACHE: 主机没开启离线功能.

IDLE: 空闲状态.

CHECKING: 正在检查本地manifest和服务器中manifest的差异

DOWNLOADING: 正在下载需要的缓存数据

OBSOLETE: 缓存已经过期

常用方法

void update(): 强制检查服务器的mainfest文件是否有更新

void swapCache(): 更新缓存,只能在applicationCache的updateReady事件被触发时调用.

setInterval(function(){

applicationCache.update()

},2000);

applicationCache.onupdateready = function(){

if(confirm("已从远程服务器下载了需要的缓存,是否更新?")){

applicationCache.swapCache();

location.reload();

}

}

4.2.3 离线应用的事件与监听

访问html页面过程

浏览器请求index.html

服务器返回index.html

浏览器页面是否制定manifest属性,若制定,触发checking事件,检查服务器中的manifest文件是否存在,不存在则触发error事件,不会制定第六部及其后续步骤

浏览器解析index.html,请求该页其他资源.

服务器返回所以请求

浏览器处理mainfest文件,重新请求manifest文件中的所以页面,包括index.html页面,前面下载过的资源,扔会再下一遍.

服务器返回所以要求被要求缓存的资源

浏览器开始下载需要在本地缓存的资源,开始下载时触发ondownloading事件,在下载过程中不断触发onprogress事件.以便开发人员了解下载进度.

下载完成后触发oncache事件.缓存完成

当用户再访问index.html时,前面1~5完全相同,接下来检测mainfest文件是否有改变.

没有改变触发onnoupdate事件,结束.

mainfest改变,执行第7,8部,当所以文件本地缓存下载完毕后,浏览器- 触发onupdateready事件,而不会触发oncached事件.

5 使用worker创建多线程

worker中无法使用DOM、alert等与界面有关的操作.

使用理由:防止js阻塞主线程的js运行

WorkerAPI

onmessage: 获取前台js提交过来的数据

postMessage(data): 前台js通过postMessage触发Worker对象的onmessage事件.

importScripts(urls),导入多个js,importScripts(“a.js”,“b.js”);

sessionStorge/localStorage: 使用Worker操作Storage本地存储

Worker: 创建新的Worker对象启动嵌套线程

XMLHttpRequest: Worker使用XMLHttpRequest发送异步请求.

navigator: 与window的location属性类似

location: 与window的location属性相似

self: WorkerGlobalScope对象,代表当前Worker线程自身作用域.调用self的close()结束线程

setTimeout()/seInterval()/eval()/inNaN()/parseInt,等与界面无关的js核心函数,包括Array/Data/Math/Number/Object/String等.

写一段找出输入start和end之间素数的线程.

worker.js代码

onmessage =function(event){

var data =JSON.parse(event.data);

var start =data.start;

var end =data.end;

var result ="";

search:

for (var n =start; n <= end :n++){

if(n%i==0){

continue search;

}

result +=(n+",");

}

}

postMessage(result);

网页代码

...

var car =function(){

var start = parseInt(document.getElementById("start").value);

var end = parseInt(document.getElementById("end").value);

//创建线程

var cal = new Worker("worker.js");

var data ={

"start" : srart,

"end" : end

};

//发送数据

cal.postMessage(JSON.stringify(data));

cal.onmessage = function (evnet){

alert(event);

}

}

并行的两条Worker不能互相通信,但Wroker可嵌套.

6 客户端通信

WebSocket: 服务器主动推送信息/客户端实时推送数据到服务器

6.1 跨文档通信

window对象新增方法

targetWindow.postMessage(message,targetOrigin): 该方法用户向targetWindow中状态的HTML发送信息,targetOrigin表示接收html的域名.

onmessage: 调用方法:windows.onmessage =function(event){…}

event中的属性:

data: 数据

orgin: 发送消息window的源域名

lastEventID: 返回发送消失时间的ID

source: 返回发送消息的窗口

html想发送要做

获取接收消息的window对象

调用接收消息的window对象的postMessage(any message)方法

html想接收要做

本html绑定事件window.message = function(event){…};

跨文档消息传递

//source.html

var targetWin = window.open("接收方url",'_blank','windth=400,height=300');

targetWin.onload =function(){

targetWin.postMessage("传输消息","接收方域名");

}

window.onmessage =function(event){

//忽略其他域名发送的消息

if(event.orgin !="指定域名"){

return ;

}

alert(event.data);

}

//接收页面.html

window.onmessage = function(event){

//忽略其他域名发送的消息

if(event.orgin !="指定域名"){

return ;

}

alert("接收到消息拉!"+event.data);

event.source.postMessage("回传消息",event.origin);

}

结果:

alert(接收到消息拉!传输消息);

alert(回传消息);

注意!一定要判断发送方的域名!!!!!一定要判断发送方的域名!!!!!一定要判断发送方的域名!!!!!

6.2 WebSocket与服务器通信

以前方案:

周期发送请求

页面使用隐藏窗口与服务器长连接

WebSocket方法

send(“数据”);向服务器发送数据.

close();关闭该WebSocket.

WebSocket监听事件

onopen: 当WebSocket建立网络连接触发该.

onerror: 网络连接错误

onclose: WebScokt被关闭触发

onmessage: WebSocket接收到服务器数据时

WebSocket属性

readyState

1.1 CONNECTING(0): WebSocket正在尝试连接

1.2 OPEN(1): 已经连接

1.3 CLOSING(2): 正在关闭连接

1.4 CLOSED(3): 已经关闭连接

WebSocket与服务器通信步骤

WebSocket.Constructor(url,[DOMString protocols]);创建WebSocket对象

发送信息: WebSocket对象的send()

接收信息: WebSocket对象的onmessage属性绑定函数;

实现客户端多人聊天,JAVA为例

客户端代码:

var web_socket =new WebSocket("ws://域名:端口");

web_socket.onopen =function(){

web_socket.onmessage =function(event){

document.getElementById('show').innerHTML += event.data +""

}

};

var sendMsg =function(val){

var inputElement = document.getElementByID('msg');

webSocket.send(inputElement.value);

inputElement.value="";

}

...

服务端代码

import java.io.*;

import java.net.*;

import java.nio.charset.Charset;

import java.security.MessageDigest;

import java.util.regex.*;

import java.util.*;

import sun.misc.BASE64Encoder;

public class ChatServer

{

// 记录所有的客户端Soccket

public static List clientSockets

= new ArrayList();

public ChatServer()throws IOException

{

// 创建ServerSocket,准备接受客户端连接

ServerSocket ss = new ServerSocket(30000);

while(true)

{

// 接收到客户端连接

Socket socket = ss.accept();

// 将客户端Socket添加到clientSockets集合中

clientSockets.add(socket);

// 启动线程

new ServerThread(socket).start();

}

}

public static void main(String[] args)

throws Exception{

new ChatServer();

}

}

class ServerThread extends Thread

{

private Socket socket;

public ServerThread(Socket socket)

{

this.socket = socket;

}

public void run()

{

try

{

// 得到Socket对应的输入流

InputStream in = socket.getInputStream();

// 得到Socket对应的输出流

OutputStream out = socket.getOutputStream();

byte[] buff = new byte[1024];

String req = "";

// 读取数据,此时建立与WebSocket的"握手"。

int count = in.read(buff);

// 如果读取的数据长度大于0

if(count > 0)

{

// 将读取的数据转化为字符串

req = new String(buff , 0 , count);

System.out.println("握手请求:" + req);

// 获取WebSocket的key

String secKey = getSecWebSocketKey(req);

System.out.println("secKey = " + secKey);

String response = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: "

+ "websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: "

+ getSecWebSocketAccept(secKey) + "\r\n\r\n";

System.out.println("secAccept = " + getSecWebSocketAccept(secKey));

out.write(response.getBytes());

}

int hasRead = 0;

// 不断读取WebSocket发送过来的数据

while((hasRead = in.read(buff)) > 0){

System.out.println("接收的字节数:" + hasRead);

/*

因为WebSocket发送过来的数据遵循了一定的协议格式,

其中第3个〜第6个字节是数据掩码。

从第7个字节开始才是真正的有效数据。

因此程序使用第3个〜第6个字节对后面的数据进行了处理

*/

for (int i = 0 ; i < hasRead - 6 ; i++ ){

buff[i + 6] = (byte) (buff[i % 4 + 2] ^ buff[i + 6]);

}

// 获得从浏览器发送过来的数据

String pushMsg = new String(buff

, 6 , hasRead - 6 , "UTF-8");

// 遍历Socket集合,依次向每个Socket发送数据

for (Iterator it = ChatServer.clientSockets.iterator()

; it.hasNext() ;)

{

try

{

Socket s = it.next();

// 发送数据时,第一个字节必须与读到的第一个字节相同

byte[] pushHead = new byte[2];

pushHead[0] = buff[0];

// 发送数据时,第二个字节记录发送数据的长度

pushHead[1] = (byte) pushMsg.getBytes("UTF-8").length;

// 发送前两个字节

s.getOutputStream().write(pushHead);

// 发送有效数据

s.getOutputStream().write(pushMsg.getBytes("UTF-8"));

}

catch (SocketException ex)

{

// 如果捕捉到异常,表明该Socket已经关闭

// 将该Socket从Socket集合中删除

it.remove();

}

}

}

}

catch (Exception e)

{

e.printStackTrace();

}

finally

{

try

{

// 关闭Socket

socket.close();

}

catch (IOException ex)

{

ex.printStackTrace();

}

}

}

// 获取WebSocket请求的SecKey

private String getSecWebSocketKey(String req)

{

//构建正则表达式,获取Sec-WebSocket-Key: 后面的内容

Pattern p = Pattern.compile("^(Sec-WebSocket-Key:).+",

Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

Matcher m = p.matcher(req);

if (m.find())

{

// 提取Sec-WebSocket-Key

String foundstring = m.group();

return foundstring.split(":")[1].trim();

}

else

{

return null;

}

}

// 根据WebSocket请求的SecKey计算SecAccept

private String getSecWebSocketAccept(String key)

throws Exception

{

String guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

key += guid;

MessageDigest md = MessageDigest.getInstance("SHA-1");

md.update(key.getBytes("ISO-8859-1") , 0 , key.length());

byte[] sha1Hash = md.digest();

BASE64Encoder encoder = new BASE64Encoder();

return encoder.encode(sha1Hash);

}

}

[javascript](http://mzkmzk.github.io/blog/categories/javascript/)

【我有一个前端学习交流QQ群:328058344 如果你在学习前端的过程中遇到什么问题,欢迎来我的QQ群提问,群里每天还会更新一些学习资源。禁止闲聊,非喜勿进。】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目录 第1章 HTML 5简介 1 1.1 HTML历史与HTML 5 2 1.2 HTML 5的优势 6 1.3 HTML 5的基本结构和语法变化 8 1.4 本章小结 12 第2章 HTML 5的常用元素与属性 14 2.1 HTML 5保留的常用元素 15 2.2 HTML 5增强的iframe元素 34 2.3 HTML 5保留的通用属性 40 2.4 HTML 5新增的通用属性 44 2.5 HTML 5新增的结构元素 48 2.6 HTML 5新增的语义元素 55 2.7 HTML 5头部和元信息 59 2.8 HTML 5新增的拖放API 63 2.9 本章小结 71 第3章 HTML 5表单相关的元素和属性 72 3.1 HTML原有的表单及表单控件 73 3.2 HTML 5新增的表单属性 83 3.3 HTML 5新增的表单元素 90 3.4 HTML 5新增的客户端校验 96 3.5 本章小结 100 第4章 HTML 5的绘图支持 101 4.1 使用canvas元素 102 4.2 绘图 103 4.3 坐标变换 118 4.4 控制叠加风格 123 4.5 控制填充风格 124 4.6 位图处理 128 4.7 输出位图 132 4.8 动画制作 133 4.9 本章小结 136 第5章 HTML 5的多媒体支持 137 5.1 使用audio和video元素 138 5.2 使用JavaScript脚本控制媒体播放 141 5.3 事件监听 144 5.4 track元素 146 5.5 本章小结 149 第6章 级联样式单与CSS选择器 150 6.1 样式单概述 151 6.2 CSS样式单的基本使用 152 6.3 CSS选择器 158 6.4 伪元素选择器 167 6.5 CSS 3新增的伪类选择器 176 6.6 在脚本修改显示样式 195 6.7 本章小结 197 第7章 字体与文本相关属性 198 7.1 字体相关属性 199 7.2 CSS 3支持的颜色表示方法 205 7.3 文本相关属性 206 7.4 CSS 3新增的服务器字体 212 7.5 本章小结 215 第8章 背景、边框和边距相关属性 216 8.1 盒模型简介 217 8.2 背景相关属性 217 8.3 使用渐变背景 226 8.4 边框相关属性 239 8.5 使用opacity控制透明度 246 8.6 padding和margin相关属性 247 8.7 本章小结 249 第9章 大小、定位、轮廓相关属性 250 9.1 width、height相关属性 251 9.2 定位相关属性 255 9.3 轮廓相关属性 257 9.4 用户界面和滤镜属性 258 9.5 本章小结 263 第10章 盒模型与布局相关属性 264 10.1 盒模型和display属性 265 10.2 对盒添加阴影 275 10.3 布局相关属性 278 10.4 CSS 3新增的多栏布局 285 10.5 使用弹性盒布局 289 10.6 本章小结 306 第11章 表格、列表相关属性及media query 307 11.1 表格相关属性 308 11.2 列表相关属性 313 11.3 控制光标的属性 316 11.4 media query和响应式布局 317 11.5 本章小结 323 第12章 变形与动画相关属性 324 12.1 CSS 3提供的变形支持 325 12.2 CSS 3新增的3D变换 337 12.3 CSS 3提供的Transition动画 341 12.4 CSS 3提供的Animation动画 345 12.5 本章小结 349 第13章 JavaScript语法详解 350 13.1 JavaScript简介 351 13.2 数据类型和变量 356 13.3 基本数据类型 364 13.4 复合类型 376 13.5 运算符 381 13.6 语句 391 13.7 流程控制 395 13.8 函数 403 13.9 函数的参数处理 425 13.10 面向对象 429 13.11 创建对象 437 13.12 本章小结 443 第14章 DOM编程详解 444 14.1 DOM模型概述 445 14.2 DOM模型和HTML文档 446 14.3 访问HTML元素 448 14.4 修改HTML元素 456 14.5 增加HTML元素 458 14.6 删除HTML元素 463 14.7 传统的DHTML模型 467 14.8 使用window对象 469 14.9 navigator和地理定位 479 14.10 HTML 5增强的History API 485 14.11 使用document对象 490 14.12 HTML 5新增的浏览器分析 493 14.13 本章小结 496 第15章 事件处理机制 497 15.1 事件模型的基本概念 498 15.2 绑定事件处理函数 499 15.3 事件处理函数的执行环境 505 15.4 事件类型 521 15.5 本章小结 534 第16章 本地存储与离线应用 535 16.1 Web Storage 536 16.2 Indexed数据库API 545 16.3 离线应用 564 16.4 本章小结 571 第17章 文件支持与二进制数据 572 17.1 HTML 5增强的文件上传域 573 17.2 ArrayBuffer与TypedArray 578 17.3 Blob类 583 17.4 本章小结 587 第18章 Web Worker多线程API 588 18.1 使用Worker创建多线程 589 18.2 与Worker线程进行数据交换 591 18.3 Worker线程嵌套 594 18.4 使用SharedWorker创建共享线程 597 18.5 Promise 603 18.6 本章小结 611 第19章 客户端通信 612 19.1 跨文档消息传递 613 19.2 使用WebSocket与服务器通信 621 19.3 使用Server-Sent Events API 630 19.4 使用Beacon 635 19.5 本章小结 636 第20章 HTML 5的疯狂俄罗斯方块 637 20.1 俄罗斯方块简介 638 20.2 开发游戏界面 639 20.3 俄罗斯方块的数据模型 640 20.4 实现游戏逻辑 644 20.5 本章小结 654

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值