04 Websocket和Websocketed
一、web socket事件和方法
有了HTTP协议为什么还需要Websocket这种协议呢?因为HTTP协议发起的通信只能通过客户端发起,然后服务端才可以将消息回应到客户端。因此HTTP协议做不到服务器主动向客户端推送信息。
Websocket是在单个TCP连接上进行全双工通信的协议,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
实际生产环境中实现推送技术所运用的大多都是Ajax轮询。轮询是在特定的的时间间隔,由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
简单示例:
1 var ws = new WebSocket("wss://echo.websocket.org"); 2 3 ws.onopen = function(evt) { 4 console.log("Connection open ..."); 5 ws.send("Hello WebSockets!"); 6 }; 7 8 ws.onmessage = function(evt) { 9 console.log( "Received Message: " + evt.data); 10 ws.close(); 11 }; 12 13 ws.onclose = function(evt) { 14 console.log("Connection closed."); 15 };
大概执行步骤
1. 构造函数
WebSocket 对象作为一个构造函数,用于新建 WebSocket 实例。
var ws = new WebSocket('ws://localhost:8080');
执行上边语句后,客户端会与服务器进行连接。
2. Websocket.readstate
此属性返回的是实例对象的当前状态
1 CONNECTING : 值为0,表示正在连接 2 OPEN :值为1 ,表示连接成功,可以进行通信 3 CLOSING: 值为2,表示连接正在关闭. 4 CLOSED: 值为3 ,表示连接已经关闭,或者打开连接失败
Java示例:
1 switch (ws.readyState) { 2 case WebSocket.CONNECTING: 3 // do something 4 break; 5 case WebSocket.OPEN: 6 // do something 7 break; 8 case WebSocket.CLOSING: 9 // do something 10 break; 11 case WebSocket.CLOSED: 12 // do something 13 break; 14 default: 15 // this never happens 16 break; 17 }
3. webSocket.onopen(事件)
实例对象的onopen
属性,用于指定连接成功后的回调函数。
1 ws.onopen = function () { 2 ws.send('Hello Server!'); 3 }
如果要指定多个回调函数,可以使用addEventListener
方法。
1 ws.addEventListener('open', function (event) { 2 ws.send('Hello Server!'); 3 });
4. webSocket.onclose(事件)
实例对象的onclose
属性,用于指定连接关闭后的回调函数。
1 ws.onclose = function(event) { 2 var code = event.code; 3 var reason = event.reason; 4 var wasClean = event.wasClean; 5 // handle close event 6 }; 7 8 ws.addEventListener("close", function(event) { 9 var code = event.code; 10 var reason = event.reason; 11 var wasClean = event.wasClean; 12 // handle close event 13 });
5. webSocket.onmessage(事件)
实例对象的onmessage
属性,用于指定收到服务器数据后的回调函数。
1 ws.onmessage = function(event) { 2 var data = event.data; 3 // 处理数据 4 }; 5 6 ws.addEventListener("message", function(event) { 7 var data = event.data; 8 // 处理数据 9 });
6. websocket.send(方法)
实例对象的send()方法用于向服务器发送数据
ws.send('your message');
7. webSocket.bufferedAmount
实例对象的bufferedAmount
属性,表示还有多少字节的二进制数据没有发送出去。它可以用来判断发送是否结束。
1 var data = new ArrayBuffer(10000000); 2 socket.send(data); 3 4 if (socket.bufferedAmount === 0) { 5 // 发送完毕 6 } else { 7 // 发送还没结束 8 }
8. websocket.onerror(事件)
实例对象的onerror
属性,用于指定报错时的回调函数。
1 socket.onerror = function(event) { 2 // handle error event 3 }; 4 5 socket.addEventListener("error", function(event) { 6 // handle error event 7 });
二、Websocketed服务器
它的最大特点,就是后台脚本不限语言,标准输入(stdin)就是 WebSocket 的输入,标准输出(stdout)就是 WebSocket 的输出。
举例来说,下面是一个python脚本counter.py
1 print('1') 2 sleep 1 3 4 print('2') 5 sleep 1 6 7 print('3')
命令行下运行这个脚本,会输出1、2、3,每个值之间间隔1秒。
1 2 3
现在,启动websocketd
,指定这个脚本作为服务。
$ websocketd --port=8080 python ./counter.py
上面的命令会启动一个 WebSocket 服务器,端口是8080
。每当客户端连接这个服务器,就会执行counter.py
脚本,并将它的输出推送给客户端
1 var ws = new WebSocket('ws://localhost:8080/'); 2 3 ws.onmessage = function(event) { 4 console.log(event.data); 5 };
上面是客户端的 JavaScript 代码,运行之后会在控制台依次输出1、2、3。
有了它,就可以很方便地将命令行的输出,发给浏览器。
$ websocketd --port=8080 ls
上面的命令会执行ls
命令,从而将当前目录的内容,发给浏览器。使用这种方式实时监控服务器,简直是轻而易举(代码)。