你好,WebSocket定义WebSocket是HTML5开始提供的一种在单TCP连接上进行全双工通信的协议(注意是协议)。WebSocket使得客户端和服务器之间的数据交换更加容易,允许服务器主动向客户端推送数据。在WebSocketAPI中,浏览器和服务器只需要完成一次握手,两者之间就可以直接建立持久连接,进行双向数据传输。为什么要用WebSocket原来客户端和服务端的通信是通过HTTP协议,只能由客户端发起。HTTP协议不能让服务器主动向客户端推送信息。而且,客户端和服务端通信完成后,客户端和服务端的连接就会断开,而WebSocket是长连接。建立连接时,如果其中一端不主动断开连接,则两端的连接将一直连接。和。WebSocket旨在解决类似于聊天室的场景。本来HTTP协议的单向请求特性就注定了客户端要知道服务器是否有持续的状态变化是很麻烦的。我们只能用“轮询”:每隔一段时间,发送一个查询,看看服务器是否有新的信息。轮询效率低下并且浪费资源(因为您必须保持连接,或者HTTP连接始终打开)。因此,工程师们一直在思考,有没有更好的办法。这就是WebSocket的发明方式。1:组成及特点长连接:可以在一个连接上连续发送多个数据包。在连接过程中,如果没有发送数据包,则双方都需要发送链路检查包。TCP/IP:TCP/IP属于传输层,主要解决网络中的数据传输问题,只传输数据。但是对于传输的数据没有标准的封装、解析等,使得传输的数据难以识别,所以就有了应用层协议对数据进行封装、解析等,比如HTTP协议。HTTP:HTTP是一种应用层协议,对传输的数据进行封装和解析。从HTTP1.1开始,默认开启了持久连接,即请求头中看到的Connection:Keep-alive。但是这个长连接只是说保持(服务端可以告诉客户端保持时间Keep-Alive:timeout=200;max=20;)这个TCP通道,直接Request-Response,没有创建连接通道,并且实现了性能优化。但是HTTP通信本身还是Request-Response。套接字:与HTTP不同,套接字不是一种协议。它是对传输层协议(主要可以理解为TCP/IP)在程序层面的一种接口封装。我们知道传输层的协议是为了解决网络中的数据传输,所以套接字就是传输通道两端的接口。所以对于前端来说,socket也可以简单的理解为TCP/IP的一种抽象协议。WebSocket:WebSocket被封装成一个应用层协议作为套接字,使客户端和远程服务器可以通过web建立全双工通信。websocket提供了ws和wss两种URLschemes。WebSocket实例WebSocket协议本质上是一个基于TCP的协议。为了建立WebSocket连接,客户端浏览器首先要向服务器端发起HTTP请求。这个请求不同于通常的HTTP请求,它包含一些额外的头信息。附加的头信息“Upgrade:WebSocket”表明这是一个应用协议。对于升级后的HTTP请求,服务器会解析附加的头信息,然后生成响应消息返回给客户端。客户端和服务端之间的WebSocket连接建立起来,双方可以通过这个连接通道自由的传递信息,连接会一直持续到客户端或者服务端其中之一主动关闭连接。二:WebSocket用于创建WebSocket对象varws=newWebSocket(url,[protocol]);上面代码中的第一个参数url指定了连接的URL。第二个参数protocol是可选的,它指定了可接受的子协议。1:属性ws.readyState:0-表示连接还没有建立。1-表示已建立连接并且可以进行通信。2-表示连接正在关闭。3-表示连接已关闭或无法打开连接。ws.bufferedAmount实例对象的bufferedAmount属性表示还有多少字节的二进制数据还没有发送出去。可以用来判断发送是否结束。vardata=newArrayBuffer(10000000);socket.send(data);if(socket.bufferedAmount===0){//发送完成}else{//发送未完成}2:事件开启:ws.onopen连接triggerws.onopen=function(){ws.send('HelloServer!');}如果想指定多个回调函数,可以使用addEventListener方法。ws.addEventListener('open',function(event){ws.send('HelloServer!');});message:ws.onmessage当客户端从服务器接收到数据时被触发。请注意,服务器数据可能是文本或二进制数据(blob对象或Arraybuffer对象)。error:ws.onerror发生通信错误时触发close:ws.onclose连接关闭时触发3:ws.send()方法向服务器发送数据ws.close()关闭连接机制在使用websocket的过程中,有时候会断网,但是服务器在断网的时候并没有触发onclose事件。这样,服务器就会不断地向客户端发送冗余链接,数据就会丢失。因此需要一种机制来检测客户端和服务端是否处于正常的连接状态。于是就有了websocket的心跳。还有心跳说明它还活着,没有心跳说明它已经死了。实现心跳检测的思路是:定时向服务器发送一个ping数据。正常情况下,服务器会返回一个pong给客户端。如果客户端可以通过onmessage事件监听到,说明请求正常执行心跳检测的思路是:每隔一定时间向服务端发送一个ping数据。正常情况下,服务器会返回一个pong给客户端。如果客户端可以通过onmessage事件监听到,说明请求了正常的心跳连接://添加心跳防止断开连接lettime=setInterval(()=>{ws.send('heartbeat')},9*60*1000);//每9分钟发送一次,防止断线2:websocket和http长连接的区别我们都知道现在我们普遍使用的HTTP1.1也有长连接,也就是keep-alive。那么我们在学习的时候肯定会有疑问:不都是长连接吗?有什么不同?先说comet和WebSocket的区别:comet发送http请求后,如果服务端没有返回,则一直连接。当服务器有东西要“推送”给浏览器时,相当于之前发送的http请求。返回一个http响应。然后保持了很久的http连接就断了。然后浏览器又发了一个http请求,服务器又不返回onhold,等待有什么东西“推”给浏览器,然后给http请求一个响应,然后断开连接。反复。一旦浏览器不向服务器发送http请求,服务器就不能主动向浏览器推送消息,因为没有连接的连接让你推送。WebSocket是不同的。握手后建立的连接不会断开(意外情况和主动切断的程序除外)。浏览器不需要每次收到服务器推送的消息都发起请求。而且,服务器可以随时向浏览器推送消息,而无需等待浏览器发送http请求,因为WebSocket连接一直在断。为什么会有这样的差异?这是协议层面的区别。http协议规定一个http连接是一次请求,一次响应的过程。请求必须在得到响应后终止。而且只有先有请求,才会有响应。以http1.1keep-alive为例,即使底层的tcp连接没有断,服务器无缘无故向浏览器发送一个http响应,浏览器不会接受,他也找不到接收者,因为没有相应的响应请求。可以看到ajax必须先发送请求才有onsuccess回调响应请求。这个onsuccess回调会在你的ajax没有发送的时候被调用吗?WebSocket协议不同。握手后,他规定你替我保持连接,不要断开。因此在这种情况下,浏览器服务器可以相互发送消息。在浏览器端新建一个WebSocket后,注册onmessage回调,那么这个onmessage就可以重复调用,只要有服务端的消息就可以了。而不是说一个新的WebSocketonmessage只会被调用一次,下次还得创建一个新的websocket。上面提到了http连接、tcp连接和websockt连接的区别。其实这是新人最容易理解的地方。接下来我要废话了,为什么说废话,因为我只是看了粗浅的,接下来我会根据自己的理解来解释其中的区别。网络5层分层(自下而上):物理层、数据链路层、网络层、传输层、应用层http、websocket都是应用层协议,它们规定了数据如何封装,它们的传输通道由下层。也就是说无论是http请求还是WebSocket请求,它们使用的连接都是由传输层提供的,即tcp连接(传输层也有udp连接)。只是说http1.0协议规定,当你请求得到响应后,你必须关闭连接。所以你用http协议发送的请求不能一直连接(如果服务器没有返回,可以保持很长时间,但是也会因为超时断开连接)。WebSocket协议规定,握手完成后我们的连接不能断开。WebSocket握手虽然使用http请求,但是在请求头和响应头中都有特殊的字段。浏览器或服务器收到后,会进行相应的协议转换。所以,http请求持有不返回的长连接和WebSocket的连接有着本质的区别。参考链接:https://segmentfault.com/a/11...四:node.js+express+websocket使用socket.iosocket.io实现服务端推送文档地址:https://socket.io/docs/no您可以阅读文档以了解从哪里开始:npminstallsocket.iosocket.io-client--save1:clientletsocket=io("ws://localhost:3001");//建立链接socket.emit('msg',{message:"Helloserver,I'mtheclient"});//向服务器发送消息socket.on('msg',function(data){//监听来自服务器的消息“msg”console.log(data);});2:servercodeletexpress=require('express');letrouter=express.Router();letapp=require('express')();letserver=require('http').createServer(app);letio=require('套接字.io')(server);io.on('connection',function(socket){//socket相关的监听必须放在这个回调中console.log('auserconnected');//当连接断开socket.on("disconnect",function(){console.log("ausergoout");});socket.on("msg",function(obj){//打印消息clientlet{message}=objconsole.log(message);//延时3s返回信息给客户端setTimeout(function(){io.emit("msg",'你好客户端,我是服务器');},3000);});});//开启端口监听socketserver.listen(3001);router.get('/',function(req,res,next){res.render('im/imRoom');});module.exports=路由器;运行结果:服务器:一个用户连接你好服务器,我是客户端服务器:你好客户端,我是服务器(3秒后)我是菜鸟,以上是我对websocket的一些学习,以后会继续补充未来还有很多不足
