当前位置: 首页 > Web前端 > vue.js

一篇了解WebSocket

时间:2023-03-31 21:31:08 vue.js

一篇了解WebSocketWebsocket是一种持久化网络通信协议,可以在单个TCP连接上进行全双工通信。没有Request和Response的概念,两者的地位完全平等,让服务端主动向客户端发送数据。一旦建立连接,客户端和服务器之间就可以实时进行双向数据传输。它最大的特点是服务端可以主动向客户端推送信息,客户端也可以主动向服务端发送信息。是真正的双向平等对话,属于服务器推送技术的一种。(1)基于TCP协议,服务器端实现相对容易。(2)没有同源限制,客户端可以和任何服务器通信。(3)协议标识符为ws(如果加密则为wss),服务器URL为URL。客户端由于HTML5提供了websocket,客户端可以新建一个ws对象来建立通信。letws=newWebSocket('ws://localhost:3000');ws.onopen=()=>{console.log('openconnection');}ws.onmessage=(event)=>{//Client上面的回调console.log(event,'onmessageevent');}ws.onclose=()=>{console.log('closeconnection')}是websocket的三个事件,一个是error事件,显然是发生通信错误时触发的事件。另外,websocket还有两个常用的方法,在后续的例子中会用到:ws.send();//使用连接发送数据ws.close();//关闭连接服务器节点,使用最广泛的websocket服务是通过ws模块创建的,使用前需要安装:constexpress=require('express');constSocketServer=require('ws').Server;常量端口=3000;constserver=express().listen(port,()=>{console.log(`监听${port}`);})constwss=newSocketServer({server});wss.on('connection',(ws)=>{console.log('Clientconnected.');ws.on('message',(data)=>{console.log(data);//服务器向客户端发送数据ws.send(data);})ws.on('close',()=>{console.log('Closeconnected.')})})启动服务,运行:nodeserver.js可以看到服务启动了:listening3000此时访问客户端在终端页面,可以在控制台看到:打开连接,输入ws,回车显示ws对象信息:WebSocket{binaryType:"blob"bufferedAmount:0extensions:""onclose:()=>{console.log('closeconnection')}onerror:nullonmessage:(event)=>{console.log(event,'onmessageevent');}onopen:()=>{控制台.log('打开连接');}protocol:""readyState:1url:"ws://localhost:3000/"}这里提一下readyState,返回实例对象的当前状态。状态码有四种:含义CONNECTING0表示正在连接OPEN1表示连接成功,可以通信CLOSING2表示连接正在关闭CLOSED3表示连接已经关闭或者打开连接失败这时候,手动在控制台调用send发送消息:ws.send('hello')send(实例对象的)方法用于向服务端发送数据,触发客户端的ws.onmessage事件,同时服务端的ws.on('message')事件也被触发,服务端收到客户端发送的消息,客户端打印事件返回信息:可以在data属性中看到“hello”信息。同时服务端可以主动持续向客户端发送消息:wss.on('connection',(ws)=>{console.log('Clientconnected.');constsendNowTime=setInterval(()=>{ws.send(String(newDate()))},1000)});//服务器每秒向客户端发送实时消息。客户端连接后,会开始定时从服务器接收数据,直到手动关闭连接或Serve。ws.close()模拟多人聊天下面给出一个完整的例子来模拟两个人通过websocket进行实时聊天:客户端代码

    ![](item.nickname==nickname?)

    {{项目。消息}}

发送
*{边距:0;填充:0;}ul,li{列表样式:无;}.box{宽度:500px;margin:0auto;}.boxulli{display:flex;对齐项目:弹性启动;margin-bottom:10px;}.boxulliimg{宽度:40px;高度:40px;margin-right:8px;}.boxullip{字体大小:14px;行高:20px;最大宽度:300px;背景:#f1f1f1;边界半径:4px;填充:10px20px;}.me{调整内容:flex-start;flex-direction:row;}.other{flex-direction:row-reverse;order:1}letapp=newVue({el:'#app',data(){return{socketUrl:'ws://localhost:8000?userName=',nickname:'',news:[],发送:'',userList:[]}},mounted(){this.initChatting();leturl=window.location.href;this.nickname=url.split('=')[1]},方法:{initChatting(){if(window.WebSocket){this.client=newWebSocket(this.socketUrl+this.nickname);this.client.onopen=(e)=>{if(e.type=='open'){console.log('clientconnection')}}//客户端接收回调到服务器数据this.client.onmessage=(e)=>{letdata=JSON.parse(e.data);if(datainstanceofArray==true){this.userList=data;//在线人数变化}else{//聊天信息this.news.push(data);}console.log(this.news)}this.client.onclose=(e)=>{this.client=null;}this.client.onerror=()=>{if(!this.client){console.log("服务连接失败")}}}else{alert("浏览器版本太低,不支持websocket。")}},sendMsg(){letdata={message:this.send,uid:newDate().getTime(),nickname:this.nickname,date:newDate()}this.client.send(JSON.stringify(数据))this.send="";}}})服务器代码constWebSocket=require('ws').Server;constmoment=require('moment');consturl=require('url');constquerystring=require('querystring');letwss=newWebSocket({url:'localhost',port:8000})letid=0;letonlineMemberList=[];letdefaultUser='user';wss.on('connection',(ws,req)=>{console.log('connected.')id++;ws.id=id;letarg=url.parse(req.url).query;letnameObj=querystring.parse(arg);letuserName;if(nameObj.username){userName=decodeURIComponent(username);}else{userName=defaultUser+id}letuserInfo={userName,socketId:id,date:moment().format('MMMMDoYYYY,hh:mm:ssa')}for(leti=0;i{item.send(JSON.stringify(onlineMemberList))})return;}}onlineMemberList.push(userInfo);wss.clients.forEach(item=>{item.send(JSON.stringify(onlineMemberList));})ws.on('message',(data)=>{letnewData=JSON.parse(data);控制台。log(data,'data')newData.serveDate=moment().format('MMMMDoYYYY,h:mm:ssa');wss.clients.forEach(item=>{//监听发送的数据客户端,直接原封不动的返回信息,返回所有信息item.send(JSON.stringify(newData));})})ws.on('close',(e)=>{onlineMemberList=onlineMemberList.filter(item=>{returnitem.socketId!=ws.id;})wss.clients.forEach(item=>{item.send(JSON.stringify(onlineMemberList));})})ws.on('error',(e)=>{console.log('clientexception',e)})})实现效果跨域收发信息由于websocket之间可以建立点对点的链接客户端和服务端,不需要受跨域问题影响,也可以用来解决客户端跨域问题:letws=newWebSocket("ws://localhost:8200");//建立连接ws.onopen=function(){//打开协议控制台.log("connectedsuccessfully");}ws.onmessage=function(mes){//向服务器发送数据console.log(mes);}//ws.addEventListener("message",function(e){});document.querySelector(".btn").onclick=function(){letinput=document.querySelector(".input").value;console.log("客户端向服务器发送的信息:"+input);ws.send(输入);//如果服务端关闭协议后,即执行ws.close()后,此时会报错:WebSocketisalreadyinCLOSINGorCLOSEDstate.};看完这篇文章,希望读者能够对websocket有一个初步的了解,练习可以更快上手