摘自论道《HTML5》
WebSocket
不是标准Socket
协议,它在OSI
七层模型中处于上层,基于HTTP
。HTTP
协议是TCP
协议的一部分。
特性:有状态、速度、双向通信、长轮询。
-
工作原理: 浏览器或客户端通过
80
或者443
端口与服务器进行请求握手,服务器根据HTTP
首部识别是不是WebSocket
请求,如果是,则将请求升级为一个WebSocket
连接,握手成功后就进入双向长连接的数据传输阶段。客户端通过WebSocket
与服务端进行通信时,只有第一次握手时交互的信息比较复杂,在握手成功之后便进入双向长连接的数据传输阶段,此时传输的几乎只是纯数据,性能很高。XMLHttpRequest
。使用它可以在不重新加载页面的情况下更新网页,在页面加载后在客户端向服务器请求数据,在页面加载后在服务器端接受数据,在后台向客户端发送数据。XMLHttpRequest
对象提供了对HTTP
协议的完全访问,包括做出post
和head
请求以及普通的get
请求的能力XMLHttpRequest
可以同步或异步返回Web
服务器的响应,并且能以文本或者DOM
文档的形式返回内容。'OSI
(Open System Interconnection
,开放系统互连)七层网络模型称为开放式系统互联参考模型,是一个逻辑上的定义,一个规范,它把网络从逻辑上分为了7层。这7层分别是:物理层(physical layer
)、数据链路层(datalinklayer
)、网络层(network layer
)、传输层(transport layer
)、会话层(session layer
)、表示层(presentation layer
)、应用层(application layer
)。每一层都有相关、相对应的物理设备,比如路由器、交换机。OSI
七层模型是一种框架性的设计方法,建立七层模型的主要目的是解决异种网络互连时所遇到的兼容性问题,其最主要的功能就是帮助不同类型的主机实现数据传输。它的最大优点是将服务
、接口
和协议
这3个概念明确地区分开来,通过7个层次化的结构使不同的系统、不同的网络之间实现可靠的通信。
请求和响应的消息首部
下面给出WebSocket
请求和响应的消息首部。客户端到服务端的请求代码如下:
From client to server:
GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
Sec-WebSocket-Protocol: sample
Upgrade: WebSocket
Sec-WebSocket-Key1: 4@1 46546xW%0l 1 5
Origin: HTTP://example.com
[8-byte security key]
服务端到客户端的响应代码如下:
From server to client:
HTTP/1.1 101 WebSocket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: HTTP://example.com
WebSocket-Location: ws://example.com/demo
WebSocket-Protocol: sample
[16-byte hash response]
WebSocket 检测浏览器支持代码
<html>
<div id=support></div>
<script type="text/javascript">
if(window.WebSocket){
document.getElementById("support").innerHTML = "您的浏览器支持HTML5的WebSocket协议";
}
else{
document.getElementById("support").innerHTML = "您的浏览器不支持HTML5的WebSocket协议";
}
</script>
</html>
WebSocket API 的内容
属性
WebSocket
有两个属性,分别是 readyState
和bufferedAmount
,其中bufferedAmount
是作为连接缓冲用的,而WebSocket
服务的 readyState
一共有以下4种状态。
- 0:
CONNECTING
,表示正在连接,尚未连接成功,这里有一个网络通信的握手过程。 - 1:
OPEN
,表示连接已经成功,可以通信了。这里的连接是长连接、持久连接。 - 2:
CLOSING
,表示连接准备被断开,握手将被取消。 - 3:
CLOSED
,表示连接已经断开,可以从服务器端断开,也可以从客户端断开。
任何一个连接开始的时候,其状态都必须是
CONNECTING=0
。如果ready-State
一直是CONNECTING
状态,就会报出INVALID_STATE_ERR
异常。
URL
URL
属性都是一样的,哪怕是访问同源网站(这里的URL地址必须是绝对地址)。
var Socket = new WebSocket('ws://www.test.com/');
以下三种形式都是错误的:
var Socket = new WebSocket('/');
var Socket = new WebSocket('C:\www.test.com');
var Socket = new WebSocket('http://www.test.com');
以下两种形式都是允许的、正确的:
var Socket = new WebSocket('ws://www.test.com/updates');
var Socket = new WebSocket('ws://www.test.com/updates:8080');
事件
其中 send()
方法基于成功的连接传送数据,其参数必须是字符串
( string
)格式。
事件句柄 | 事件类型 | 解 释 |
---|---|---|
onopen |
open |
连接打开 |
onmessage |
message |
用于接受从服务器传来的信息 |
onerror |
error |
当出现连接中的各种错误时,用于容错处理和排查 |
onclose |
close |
连接关闭或断开 |
send |
send |
基于成功的连接传送数据 |
在下面这个简单的例子中,bufferedAmount
属性用于确保能够保持在每50ms
一次更新的频率(如果网络能保持这个速率),如果这个速率太快,那么采用其他能够有保证的速率也可以。
var Socket = new WebSocket('ws://www.test.com:12010/updates');
Socket.onopen = function(){
setInterval(function(){
if(Socket.bufferedAmount == 0)
Socket.send(getUpdateData());
}, 50);
};
客户端样例程序
<script type="text/javascript">
//创建一个ws实例
var ws= new WebSocket('ws://www.xiuyetang.com:25000');
//打开WebSocket
ws.onopen = function(event){
//发送一个初始化消息
ws.send('向服务器发送一个消息');
//监听消息
ws.onmessage = function(event){
console.log('客户端收到消息,内容如下:'+event.data);
};
//监听ws的关闭
ws.onclose = function(event){
console.log('连接已经关闭');
};
//关闭ws连接
socket.close();
};
</script>
服务器端样例程序
var sys = require("sys");
var ws = require("websocket"); //此处是WebSocket服务器被调用
var server = ws.createServer(); //创建WebSocket服务器
server.addListener("connection", function(conn){ //当有客户端接入时
conn.send("Connection: "+conn.id); //向接入的客户端发送信息
conn.addListener("message", function(message){
//当收到客户端发送的信息时
server.broadcast("<"+conn.id+">"+message);
//向所有客户端发送信息
});
});
server.addListener("close", function(conn){ //当有客户端断开连接时
server.broadcast("Disconnected:"+conn.id); //向所有客户端发送信息
});
server.listen(25000); //启动服务,监听25000端口