赞
踩
HTTP
HTTP 是基于请求响应式的,即通信只能由客户端发起,服务端做出响应,无状态,无连接。
无状态:每次连接只处理一个请求,请求结束后断开连接。
无连接:对于事务处理没有记忆能力,服务器不知道客户端是什么状态。
以往实现即时通讯的手段:
轮询:客户端定时向服务器发送 Ajax 请求,服务器接到请求后马上返回响应信息并关闭连接。
长轮询:客户端向服务器发送 Ajax 请求,服务器接到请求后 hold 住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。
长连接:在页面里嵌入一个隐蔵 iframe,将这个隐蔵 iframe 的 src 属性设为对一个长连接的请求,服务器端就能源源不断地往客户端输入数据。
WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了
举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。(航班信息)
为什么需要webSocket
HTTP 协议有一个缺陷:通信只能由客户端发起。
这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。
轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。因此,工程师们一直在思考,有没有更好的方法。WebSocket 就是这样发明的。
它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
以往实现即 webSocket协议Tcp握手阶段是通过http通信完成的,目的是为了更好达到兼容。具体过程是我们在客户端构建一个websocket实例,并且为它绑定一个需要连接到的服务器地址,当客户端连接服务端的时候,会向服务端发送一个类似下面的http报文。
发送信息:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
Upgrade: websocket
Connection: Upgrade
|
这个就是Websocket的核心了,告诉Apache、Nginx等服务器:发起的是websocket协议。
Sec-WebSocket-Key 是一个Base64 encode的值,这个是浏览器随机生成的,告诉服务器需要验证是不是真的webScoket请求。
Sec_WebSocket-Protocol 是一个用户定义的字符串,用来区分同URL下,不同的服务所需要的协议。简单理解:今晚我要服务A,别搞错啦~
Sec-WebSocket-Version 是告诉服务器所使用的Websocket 协议版本
然后服务器会返回下列东西,表示已经接受到请求, 成功建立Websocket啦!
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chat |
依然是固定的,告诉客户端即将升级的是Websocket协议,而不是其他的。
Sec-WebSocket-Accept 这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key。服务器:好啦好啦,知道啦,给你看我的ID CARD来证明行了吧。
Sec-WebSocket-Protocol 则是表示最终使用的协议。
返回的状态码:
0 - 表示连接尚未建立。
1 - 表示连接已建立,可以进行通信。
2 - 表示连接正在进行关闭。
3 - 表示连接已经关闭或者连接不能打开。
一旦返回的状态码为101,表示客户端和服务端就建立了websocket连接,以后的通信走的都是websocket协议了,一旦建立连接之后,我们就可以进行数据传输了!
其他特点包括:
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws
(如果加密,则为wss
),服务器网址就是 URL。
nodejs服务端实现
见demo
WebSocket 对象作为一个构造函数,用于新建 WebSocket 实例。
var ws = new WebSocket('ws://localhost:8080');
执行上面语句之后,客户端就会与服务器进行连接。
实例对象的onopen
属性,用于指定连接成功后的回调函数。
- ws.onopen = function () {
- ws.send('Hello Server!');
- }
4.3 webSocket.onclose
实例对象的onclose
属性,用于指定连接关闭后的回调函数。
实例对象的onmessage
属性,用于指定收到服务器数据后的回调函数。
-
- ws.onmessage = function(event) {
- var data = event.data;
- // 处理数据
- };
-
- ws.addEventListener("message", function(event) {
- var data = event.data;
- // 处理数据
- });
实例对象的send()
方法用于向服务器发送数据。
发送文本的例子。
ws.send('your message');
发送 Blob 对象的例子。
- var file = document
- .querySelector('input[type="file"]')
- .files[0];
- ws.send(file);
发送 ArrayBuffer 对象的例子。
- var img = canvas_context.getImageData(0, 0, 400, 320);
- var binary = new Uint8Array(img.data.length);
- for (var i = 0; i < img.data.length; i++) {
- binary[i] = img.data[i];
- }
- ws.send(binary.buffer);
实例对象的onerror
属性,用于指定报错时的回调函数。
- socket.onerror = function(event) {
- // handle error event
- };
-
- socket.addEventListener("error", function(event) {
- // handle error event
- });
以下见案例----
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。