背景简单描述一下需求场景:应用需要客户端到客户端的通信,websocket可以很好的做到这一点。目前,网易云IM等信信的功能也是使用websocket来实现的。必要性对于前端开发者来说,目前有很多第三方工具可以提供mock服务。基本上和后端开发者就请求路径、请求字段、响应字段等达成一致后,前后端就可以独立开发了。但是websocketserver和httpserver最大的区别就是websocketserver必须一直提供服务,否则client之间是无法通信的。为了体现前后端分离,提高开发效率的本质。一味的先把所有的逻辑写完再和后台联合调试肯定是不行的,所以在和后台约定好接口名称和数据格式后,决定用nodejs写一个简单的websocket通信服务。websocket使用比较多的功能是传输文本(简单来说就是一个字符串),所以这个字符串携带了接收方的用户ID(toId),以及其他信息(比如消息类型类型和消息内容数据等).),通常的做法是将JSON.stringfy()转换成字符串,服务端将发送方的用户ID(fromId)、其他信息(如发送的消息类型、消息内容数据)转发给接收方,接收方收到字符串后,JSON.parse()进行下一步。用下图描述我希望websocket服务端能够提供给客户端的功能。客户端websocket提供的常用方法有:new、onopen、onclose、onerror、onmessage、send毫无疑问,对于前端开发者来说,需要结合业务逻辑并重点关注的方法有以下三个:newin连接到websocket服务器时传递你自己的idconstws=newWebSocket(`ws://localhost:8080/websocketServer/${id}`);send向服务器发送消息(字符串),服务器转发给目标constmsgObj={toId:666,type:'hello',data:'message......'};constmsgStr=JSON.stringfy(msgObj);ws.send(msgStr);sendTo不能接收对象或者数组类型,因为发送数据,每次都要写一个临时对象,然后调用JSON.stringfy()方法转换成一个细绳。然后封装一个适合自己业务场景的方法,简化开发过程中实现发送功能的步骤。//原型对象上添加的sendTo方法;这个。发送(味精);}}//调用表单ws.sendTo(toId,type,data);onmessage接收消息,通常是根据消息中type的不同值:做某事给对方回应(调用sendTo方法)ws.onmessage=function(msg){const{fromId,type,data}=JSON.parse(味精);switch(type){case'message'://dosomethingyourselfbreak;case'hello'://返回一条消息this.sendTo(fromId,'response','responsedata');}}最后简单封装一下初始化方法,方便不同地方使用。constwsUrl='ws://localhost:8080/';constwsPath='socketServer/';//生成一个实例letws=null;constconnect=async()=>{ws=awaitconnectWS(uid,messageHandle);//...//...//连接成功后做一些事情}functionconnectWS(uid,msgHandle){if(!WebSocket.prototype.sendTo){WebSocket.prototype.sendTo=function(toId,type,data){constmsg=JSON.stringify({toId,type,data});这个。发送(味精);}}returnnewPromise((resolve,reject)=>{constws=newWebSocket(`${wsUrl}${wsPath}${uid}`);ws.onopen=()=>{console.log('打开');解决(ws);};ws.onclose=()=>{console.log('close');};ws.onerror=()=>{console.log('error');};ws.onmessage=(msg)=>{msgHandle(JSON.parse(msg.data));};});}//接收消息处理函数functionmessageHandle(msgData){const{fromId,类型,数据}=msgData;开关(类型){案例'':中断;默认值:中断;}}服务器端常用的nodejs-websocket和express-ws这两个框架需要维护一个对象记录每个哪个用户是websocket连接,从而实现消息转发以express-ws为例:先记录连接,服务端需要记录当前连接的用户,以便转发消息时,能够正确发送到目标。转发消息服务器以从发送者那里收到的toId值作为转发的目标(接收者),在服务器自己维护的对象中找到接收者的连接,然后将发送者的身份作为fromId转发给接收者。constexpress=require('express');constexpress_ws=require('express-ws');constapp=express();constwsObj={};express_ws(app);app.ws('/socketServer/:uid',(ws,req)=>{constuid=req.params.uid;wsObj[uid]=ws;ws.onmessage=(msg)=>{let{toId,type,data}=JSON.parse(msg.data);constfromId=uid;if(fromId!=toId&&wsObj[toId]){//wsObj[toId]表示接收方和服务器之间的连接//wsObj[fromId]表示发送方和服务器之间的连接服务器栏连接wsObj[toId].send(JSON.stringify({fromId,type,data}))}}});app.listen(8080);
