使用WebSocket的原因传统的http协议有一个根本性的缺陷,就是请求只能由客户端向服务端发起,服务端收到请求后会响应并将数据返回给客户端。也就是说,服务端是没有办法主动给客户端发送消息的。这样,如果服务器的状态经常变化,客户端要实时知道这些状态就会很麻烦。例如在线多人游戏、聊天室等。一种可能的解决方案是使用轮询。轮询是指浏览器通过JavaScript启动一个定时器,然后每隔一定时间向服务器发送请求,询问服务器是否有新消息。这种机制不仅效率低,不实时,而且频繁的请求也会对服务器造成很大的压力。另一个比较靠谱的技术是HTML5的EventSource。EventSource接口用于接收服务器发送的事件。它通过HTTP连接到服务器,接收文本/事件流格式的事件,并且不关闭连接。与WebSocket相比,这项技术要简单得多,但它只是从服务端向客户端单向传输数据,不能实现真正意义上的全双工通信。因此,WebSocket是目前最好的选择。有兴趣了解EventSource的朋友可以点这里WebSocket协议WebSocket是HTML5中的一个新协议,诞生于2008年,最大的特点是服务端可以主动向客户端推送消息,客户端也可以主动发送信息到服务器,这是一个无限的全双工通信。该协议具有以下特点:握手阶段使用HTTP协议建立连接,因此WebSocket连接必须由浏览器发起。基于TCP协议,服务器端实现相对容易。它可以接收和发送两种类型的数据,一种是文本,一种是二进制数据(blob对象或Arraybuffer对象)。一般情况下,我们可以发送JSON格式的文本,这样在浏览器中处理起来非常方便。数据格式相对轻量级,性能开销小,通信高效。请求是以ws://开头的地址(如果加密,则为wss://)。WebSocket协议本身不需要同源策略,即地址为“http://a.com”的网页可以通过WebSocket连接到“ws://b.com”。但是浏览器会向服务器发送OriginHTTP头,服务器可以根据Origin拒绝WebSocket请求。浏览器支持ChromeFirefoxIE>=10Sarafi>=6Android>=4.4iOS>=8服务端实现的编程语言和框架不同,实现方式也不同。这里主要说一下如何用node来实现。node有几种常用的实现:Socket.IOWebSocket-NodeμWebSockets具体如何使用可以查看各自的API。接下来要详细介绍的是另一个WebSocket模块ws。通过npminstallws--save后,我们就可以编写一个简单的WebSocket服务端程序了。//首先导入ws模块letWebSocket=require('ws');//通过ws模块的Server类实例化一个websocket服务器letwebSocketServer=newWebSocket.Server({port:8030},err=>{console.log('TheWebSocketServeralreadyrunningon:8030');});//监听客户端请求访问的连接事件。连接建立后,回调函数会传入WebSocket连接实例对某些事件进行不同的处理。这里,客户端通过响应消息事件,发送一条消息,然后返回一条消息。ws.on('message',mes=>{console.log(`Messagesentbyclient:${mes}`);ws.send(`服务器响应的数据:${mes}`,err=>{if(err){console.log(`服务器错误:${err}`);}})})})也可以扩展http服务器,基于它搭建WebSocket服务器。constKoa=require('koa');constWebSocket=require('ws');constbodyParser=require('koa-bodyparser');constcontroller=require('./controller.js');constserver=newKoa();constwebSocketServer=newWebSocket.Server({server},()=>console.log('TheWebSocketServeralreadyrunningon:8030'));//添加一个broadcast()方法用于websocket服务器webSocketServer。broadcast=data=>{//通过遍历webSocketServer.clients,找到所有与服务器成功建立websocket连接的客户端,发送相同的消息for(constclientofwebSocketServer.clients){if(client.readyState===WebSocket.OPEN){client.send(data,err=>console.log(`服务器错误:${err}`));}}}webSocketServer.on('connection',ws=>{console.log(`服务器已连接`);ws.on('message',mes=>{console.log(`客户端发送的消息:${mes}`);//收到其中一个客户端的消息后,广播给同时连接的所有客户端constdata={message:mes}webSocketServer.broadcast(JSON.stringify(data))})})server.use(bodyParser());server.use(controller());server.listen(8030);console.log('服务器运行在8030...');现在,websocket服务器与http服务器通信,同时使用8030端口。发送请求时,会先判断是否是ws请求。如果是,则由WebSocketServer的回调函数处理,否则,仍然按照http服务器回调的正常方式处理。另外,我们注意到WebSocketServer中增加了一个broadcast()方法,用于向所有与服务器成功建立WebSocket连接的客户端广播消息。每当从其中一个客户端收到一条消息时,该消息就会发送到所有WebSocket连接。基于这个方法,我们可以构建一个聊天室应用的后台服务。ws模块的完整使用方法请看这里Clientimplementation客户端创建WebSocket连接比较简单。这是一个简单的例子://创建一个WebSocket连接:varws=newWebSocket('ws://localhost:8030/ws');ws.onopen=function(event){console.log("连接打开");//向服务器发送消息:ws.send("HelloWebSocket!");};//响应onmessage事件:ws.onmessage=function(event){console.log(event.data);};//也可以指定接收到的二进制数据类型为blob对象ws.binaryType="blob";ws.onmessage=function(event){console.log(event.data.size);};//或//指定接收到的二进制数据类型是ArrayBuffer对象ws.binaryType="arraybuffer";ws.onmessage=function(event){console.log(event.data.byteLength);};详细的属性和方法可以在这里找到另外,使用ws模块提供的WebSocket构造函数也可以作为客户端创建连接。letws=newWebSocket('ws://localhost:8030/ws');//打开WebSocket连接后立即发送消息ws.on('open',()=>{console.log(`Clientopen`);ws.send('HelloWebSocket!');});//响应接收到的消息ws.on('message',mes=>{console.log(mes);});参考链接http://www.ruanyifeng.com/blo...https://www.liaoxuefeng.com/w...http://es6.ruanyifeng.com/#do...https://developer.mozilla.org。..
