WebSocket研究
1.简介
WebSocket protocol 是HTML5一种新的协议。它是实现了浏览器与服务器全双工通信(full-duplex)。HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽并达到实时通讯。
WebSocket的出现是基于Web应用的实时性需要而产生的。这种实时的Web应用大家应该不陌生,在生活中都应该用到过,比如新浪微博的评论、私信的通知,腾讯的WebQQ等。WebSocket通过浏览器提供的API实现了具备像C/S架构下的桌面系统的实时通讯能力。其原理是使用JavaScript调用浏览器的API发出一个WebSocket请求至服务器,经过一次握手,和服务器建立了TCP通讯,因为它本质上是一个TCP连接,所以数据传输的稳定性强和数据传输量比较小。WebSocket具有web TCP之称。
2.WebSocket协议
WebSocket 协议本质上是一个基于 TCP 的协议。为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息”Upgrade: WebSocket”表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。
客户端发送到服务器的内容:
GET ws://echo.websocket.org/?encoding=text HTTP/1.1
Origin: http://websocket.org
Cookie: __utma=99as
Connection: Upgrade
Host: echo.websocket.org
Sec-WebSocket-Key: uRovscZjNol/umbTt5uKmw==
Upgrade: websocket
Sec-WebSocket-Version: 13
如果服务器支持webSocket协议,返回以下内容:
HTTP/1.1 101 WebSocket Protocol Handshake
Date: Fri, 10 Feb 2012 17:38:18 GMT
Connection: Upgrade
Server: Kaazing Gateway
Upgrade: WebSocket
Access-Control-Allow-Origin: http://websocket.org
Access-Control-Allow-Credentials: true
Sec-WebSocket-Accept: rLHCkw/SKsO9GAH/ZSFhBATDKrU=
Access-Control-Allow-Headers: content-type
就这样,WebSocket连接取代了HTTP连接,基于同样的底层TCP/IP连接。WebSocket默认使用相同的端口HTTP(80)、HTTPS(443)。
3.HTML5 WebSocket API
开发者可以使用下列内容调用浏览器WebSocket。
[Constructor(in DOMString url, optional in DOMString protocol)]
interface WebSocket {
readonly attribute DOMString URL; #WebSocket 服务器的网络地址,协议通常是”ws”或“wss(加密通信)”
// ready state
const unsigned short CONNECTING = 0; #表示还没建立连接
const unsigned short OPEN = 1; # 已经建立连接,可以进行通信
const unsigned short CLOSED = 2; # 连接已关闭,或无法打开
readonly attribute unsigned short readyState;
readonly attribute unsigned long bufferedAmount;
// networking
attribute Function onopen; #连接建立,即握手成功触发的事件
attribute Function onmessage; #收到服务器消息时触发的事件
attribute Function onclose; #关闭连接触发的事件
boolean send(in DOMString data); # 发送信息
void close(); #关闭连接
};
WebSocket implements EventTarget;
调用接口实例:
var myWebSocket = new WebSocket("ws://www.websockets.org");
myWebSocket.onopen = function(evt) { alert("Connection open ..."); };
myWebSocket.onmessage = function(evt) { alert( "Received Message: " + evt.data); };
myWebSocket.onclose = function(evt) { alert("Connection closed."); };
myWebSocket.send("Hello WebSockets!");
myWebSocket.close();
客户端是由浏览器提供了API,所以只要使用JavaScript来简单调用即可,而服务器端是要自己实现的。
4.Node.js的WebSocket模块
nodejs有很多websocket的三方库,都很实用,在stackoverflow上有人问过具体应该使用哪个库,而回答者给与了较为全面的解答,这里面对各个websocket库进行了一个对比,可以根据自己的需要选择。
其中可以注意一下socket.io,它对不同的浏览器有比较好的支持,在不支持websocket的时候可以转变成ajax的轮询等其他的替换,浏览器的支持也相当不错。同时还能和目前比较流行的node的web框架express相结合,其文档的例子写的很好。
由于我只是想搭建一个简单快捷的WS服务器,所以选用了号称probably the fastest WebSocketlibrary for node.js的ws
安装ws:
npm install --save ws
参考ws模块对Express的支持构建WebSocket服务端:
var express = require('express')
, http = require('http')
, WebSocketServer = require('ws').Server;
var app = express();
app.set('port', 80);
var server = http.createServer(app).listen(app.get('port'), function(){
console.log('my app server listening on port: '+app.get('port'));
});
wss = new WebSocketServer({ server: server });
wss.on('connection', function connection(ws) {
ws.send('you join in chat room');
wss.broadcast('new user join in');
ws.on('message', function incoming(message) {
wss.broadcast(message);
});
ws.on('close', function close(){
wss.broadcast('you go out of the chat room');
});
});
wss.broadcast = function broadcast(data) {
wss.clients.forEach(function each(client) {
client.send(data);
});
};
启动服务端
客户端
为了方便,客户端直接在coffeescript上写:
ws = new WebSocket("ws://localhost:80")
ws.onopen = (event)->
ws.onclose = (event)->
ws.onmessage = (event)->
alert event.data
setTimeout =>
ws.send "逗比们我来了"
, 2000
setTimeout =>
ws.send "逗比们我走了"
, 3000
setTimeout =>
ws.close()
alert "你已离开聊天室"
, 4000
点击”Run”
连接成功后服务器返回信息,简单的聊天室完成。
5.参考文档
http://www.websocket.org/aboutwebsocket.html
http://my.oschina.net/u/1266171/blog/357488
http://bbs.html5cn.org/forum.php?mod=viewthread&tid=149240&highlight=websocket