文章导读:javascript
1.1 为何咱们须要WebSocket这样的实时的通讯协议?html
WebSocket是web通讯方式的一种,像咱们熟知的HTTP协议也是web通讯方式的一种。可是咱们知道HTTP协议是一种无状态的协议,其服务端自己不具有识别客户端的能力,必须借助外部的一些信息好比说session和cookie,才能与特定的客户端保持通讯。也就是说咱们所发送的每个HTTP的请求都会带上请求头中一些相应的信息还有cookie,这明显会增长咱们传输的信息的体量从而带来必定的网络延迟,对于一些对通讯的实时性要求比较高的应用来讲就是不可忍受的了,好比说聊天程序或者是运行在浏览器中的实时小游戏。最郁闷的却仍是这些头信息和cookie每每对于服务器响应客户端的请求来讲是多余的,也就是说虽然我每一个请求都带了这些信息,可是服务器与客户端的交互过程当中可能根本用不上这些信息。java
为了改善HTTP请求的这种网络延迟的状况,也出现了一些适应不一样需求的其余的[web通讯]方式,好比说:轮询,长轮询(long-polling),数据流,EventSouce等等,WebSocket即是其中一种。node
实际上大多数基于因特网(或者局域网)的网络连接一般都包含长链接和基于TCP套接字的双向消息交换。可是TCP协议是属于最底层的网络通讯协议了,让一些不能信任的客户端脚本去访问底层的TCP套接字显然是不太安全的,所以WebSocket实现了一种较为安全的方案,它容许客户端脚本在客户端和支持WebSocket协议的服务器之间建立双向的套接字链接。从而使实时通讯的某些网络操做变得简单。git
1.2 WebSocket是如何工做的?github
咱们知道了WebSocket的主要做用是,容许服务器端与客户端进行全双工(full-duplex)的实时通讯。这里有个例子特别好:HTTP协议像发电子邮件,发出后必须等待对方回信;WebSocket则是像打电话,服务器端和客户端能够同时向对方发送数据,它们之间存着一条持续打开的数据通道。web
咱们先看一下一个基于WebSocket协议通讯的请求头和响应头(下面简单实例中的一个消息头):express
其中与WebSocket协议相关的信息:npm
1 Upgrade:websocket-------HTTP1.1协议规定,Upgrade头信息表示将通讯协议从HTTP/1.1转向该项所指定的协议; 2 Connection:Upgrade------表示浏览器通知服务器,若是容许,就将通讯协议升级到websocket协议; 3 Origin------------------用于验证浏览器域名是否在服务器许可的范围内; 4 Sec-WebSocket-Key-------则是用于握手协议的密钥,是base64编码的16字节随机字符串;
5 Sec-WebSocket-Accept----是服务器在浏览器提供的Sec-WebSocket-Key字符串后面,添加“258EAFA5-E914-47DA-95CA-C5AB0DC85B11” 字符串,而后再取sha-1的hash值。浏览器将对这个值进行验证,以证实确实是目标服务器回应了webSocket请求;
6.Sec-WebSocket-Location--通常状况下还有这个响应消息头用来表示进行通讯的WebSocket网址,这里面多是由于我例子中设置了127.0.0.1,因此这个信息省略掉了。
客户端经过一个WebSocket握手的过程创建一个WebSocket链接。整个过程看起来是这个样子的:json
完成握手之后,WebSocket协议就在TCP协议之上,客户端和服务器端就能够开始传送数据了。
websocket协议用ws表示,加密的websocket协议用wss协议,就像普通的HTTP协议用http表示,加密的HTTP协议用https表示同样。
下面咱们就经过一些实例看一下websocket的不一样实现是如何应用的。
咱们能够经过跑起来这个简单的实例看一下如何编写运行在浏览器中的WebSocket客户端,而且看它是怎样与服务器端交互的。
2.1 运行实例
咱们把客户端代码和服务端代码准备好,而后启动服务器监听端口,好比说8080,再而后运行咱们的客户端代码便可看到效果。
咱们的客户端代码写在html文件中:
[查看源码]
咱们经过它创建链接而且监听open和messege等事件,与此同时,咱们想要获得服务器的响应。服务器端的js代码:
[查看源码]
这个简单的websocket服务器使用了[ws模块],若是没有安装过,要先安装一下:
1 sudo npm install ws
而后在咱们的命令行执行:
1 node simpleWSserver.js
咱们的服务器启动以后,咱们运行客户端代码能够看到:
浏览器:
命令行:
整个过程看起来是这个样子的:
2.2 运行在浏览器中的websocket客户端
咱们在浏览器中的websocket主要作的事情无非是如下几个:
1 创建链接和关闭链接 2 发送数据和接收数据 3 处理错误
对应的会触发如下的事件:
1 onopen 2 onmessage 3 onclose 4 onerror
2.2.1 创建链接和关闭链接
一般咱们新建了一个WebSocket的实例就能够创建一个链接:
1 if(window.WebSocket != undefined) { 2 var socket = new WebSocket("ws://127.0.0.1:8080/"); 3 }
创建链接以后的WebSocket实例有一个readyState属性,用来标识当前的状态:
0-正在链接 1-链接成功 2-正在关闭 3-关闭成功
链接成功后会触发onopen事件,这时咱们就能够向服务器发送数据了:
1 var onOpen = function() { 2 console.log("Socket opened."); 3 socket.send("Hi, Server!"); 4 } 5 socket.onopen = onOpen;
要是关闭链接的话就会出发onclose事件:
1 var onClose = function() { 2 console.log("Socket closed."); 3 } 4 socket.onclose = onClose;
2.2.2 发送数据和接收数据
在链接创建成功后触发的onopen事件中咱们经过send()方法发送数据给服务器:
1 socket.send("Hi, Server!");
除了发送字符串类型的数据,也可使用 Blob 或 ArrayBuffer 对象发送二进制数据。不只如此,咱们还能够发送JSON数据:
1 var onOpen = function() { 2 var msg = { 3 type: "message", 4 text: "something", 5 id: "number", 6 date: Date.now() 7 }; 8 9 // Send the msg object as a JSON-formatted string. 10 socket.send(JSON.stringify(msg)); 11 } 12 socket.onopen = onOpen;
这时会触发服务器端的message事件:
1 ws.on('message', function incoming(message) { 2 console.log('received: %s', message); 3 });
同时,服务器端发来信息的时候:
1 ws.send('something');
也会触发客户端的onmessage事件:
1 var onMessage = function(data) { 2 console.log("We get signal:"); 3 console.log(data); 4 } 5 socket.onmessage = onMessage;
2.2.3 处理错误
发生的错误会触发onerror事件:
1 var onError = function() { 2 console.log("We got an error."); 3 } 4 socket.onerror = onError;
WebSocket在Node中的实现[WebSocket-Node]使咱们能够在Nodejs中使用websokcet开发客户端和服务器端实时交互的应用程序。咱们能够运行客户端和服务器实时交换随机数的例子看看它是怎么工做的:
启动服务器:
node socketserver.js
[查看源码]
启动客户端:
node socketclient.js
[查看源码]
如今很流行的websocket的实现socket.io一样包括客户端和服务器端两部分。它不只简化了接口,使得操做更容易,并且对于那些不支持WebSocket的浏览器,会自动降为Ajax链接,最大限度地保证了兼容性。它的目标是统一通讯机制,使得全部浏览器和移动设备均可以进行实时通讯。
4.1 socket.io与WebSocket的区别在哪里呢?
websocket是浏览器对象,websocket api是浏览器提供给咱们的用于浏览器和服务器实时通讯的接口。
websocket在node中的实现使咱们能够开发服务端程序时使用websocket的特性。
在咱们使用websocket的时候,由于他是浏览器提供的接口,因此会涉及到一些兼容性和支持性的问题。若是咱们对程序所运行的环境或局限不是那么了解的化,那么可能会出现问题:
[Differences between socket.io and websocket] 。而socket.io则是进化了的websocket api。socket.io创建在websocket之上,它在合适的时候使用websocket。
4.2 socket.io实现聊天室
使用websocket或socket.io能够从一个简单的聊天室程序开始。对于socket.io来讲,这很是容易。
基于node,这里使用express和socket.io:
1 npm install --save express@4.10.2 2 npm install --save socket.io
那么咱们就能够开始写聊天程序了。它须要的就是一个客户端的聊天窗口和一个用来接收消息和分发消息的服务器。
咱们须要三个文件,分别新建:package.json,index.js,index.html.
package.json:
index.js:
index.html:
先运行:
node index.js
在打开两个http://localhost:3000的窗口就能够开始聊天了:
[查看源代码]
socket.io官网上有很详细的使用方法和教程:[socket.io doc]
[web通讯]
[WebSocket-Node implementation]