宝哥软件园

Node.js websocket使用socket.io库实现实时聊天室

编辑:宝哥软件园 来源:互联网 时间:2021-09-06

了解websocket

WebSocket协议是一种新的HTML5协议。它实现了浏览器和服务器之间的全双工通信。最初的握手需要通过HTTP请求来完成。

其实websocket并不是很依赖http协议,也有自己的协议机制,但是我们这里需要用到的socket.io需要依赖Http。我之前写过一篇用java jsp聊天的文章。其实实现逻辑并不难,但大部分时间都花在UI设计上。它的实现原理是基于websocket的通信。如果你想成为一个好的聊天室,我认为大部分精力应该花在与用户视觉层的互动上。

别废话了,我们先来看看websocket和传统ajax的区别。在过去,如果我们想获得服务器的更新信息,我们可以使用ajax轮询来完成它。然而,这样做的缺点是我们增加了与服务器的交互次数。但是,大部分的互动都是没有意义的,因为我们只是做一个探究。如果没有新的信息,我们几乎不需要做任何事情,这样会大大浪费服务器资源和带宽。但是使用websocket会使客户端和服务器之间产生很长的连接,当服务器有新的消息时,可以主动推送给客户端,这样我们就不用一遍又一遍的问服务器是否有新的消息,而是由服务器直接推送给客户端,这样在没有消息的情况下,客户端就不会频繁的请求服务器了。使用websocket的特点是服务器可以主动向客户端推送消息。

使用socket.io库实现实时聊天

这也是这篇博文的主题。Socket.io发布在npm平台上,我们可以直接安装在当前的**node_modules目录下。

NPM安装插座。接下来,我们可以使用require方法直接介绍这个模块

const socket=require(' socket . io ');在创建这个websocket服务器之前,它需要依赖一个已经创建的http服务器。

让socket server=socket . listen(require(' http ')。createserver ((req,resp)={//返回页面resp.end (require ('fs ')。readfilesync('。/socket test1 . html’);}).listen(9999,' localhost ',()={ console . log(' listening ');}));在上面的代码中,socketIOTest1.html是当前目录中的一个html文件,我将在下面发布详细的代码,这里简单介绍一下。

websocket server对象中有一个连接事件,当客户端连接到套接字服务器时会触发该事件。让我们听听这个事件,并打印一个句子来指示存在用户连接。

//侦听socketserver.on ('connection ',socket={console.log('有用户连接')上的连接事件;}在上面的代码中,callback有一个参数socket,它是一个连接到客户端的socket端口对象。此对象有一个消息事件。当客户端向服务器推送消息时,事件循环会取出与该事件对应的回调函数并执行。

socket.on('message ',msg={ console . log(msg);});同时,socket对象还可以监视断开事件,以监视用户的断开

插座。on ('disconnect ',()={console。日志(“用户退出连接”);});因为我们这次的主题是打造一个可以实时聊天的聊天室,这还不够。我们还需要一个可以与用户互动的客户端。下面是我的socketIOTest代码:

!DOCTYPE html html lang=' en ' head meta charset=' UTF-8 ' title document/title/head dy text area name=' id=' content ' cols=' 30 ' row=' 10 '/text area input id=' write ' type=' text ' placeholder='请在此处写入内容' input id=' send ' type=' button ' value=' send '/script src=' http 3360。/socket.io/socket.io.js'/script脚本让send=document . getelementbyid(' send ');let write=document . getelementbyid(' write ');let content=document . getelementbyid(' content ');let socket=io . connect();//发送消息send . onclick=()={ let msg=write . value;//content . innerhtml=content . value msg ' n ';socket . send(msg);};//收到了socket.on ('message ',msg={console.log '(从服务器收到的消息:' msg ');//更新内容。innerhtml=内容。valuemsg ' n});Socket.on ('disconnect ',)={ console . log(' disconnect from server ');});/script/body/html在上面的代码中,我引入了一个带有脚本标签的socket.io.js文件,可以直接导入,无需下载,因为socket.io.js包含在socket.io模块中。在上述节点的程序代码中,我们通过require方法引入了socket.io模块,因此可以通过相对路径直接访问。

脚本src=' http:/socket . io/socket . io . js '/脚本接下来,我们可以在脚本标记中像使用服务器一样使用代码。

let socket=io . connect();使用io.connect()方法连接到websocket服务器,该方法返回与连接的服务器相对应的socket端口对象。

接下来,我们还收听消息和断开事件。

//收到了socket.on ('message ',msg={console.log '(从服务器收到的消息:' msg ');//更新内容。innerhtml=内容。valuemsg ' n});Socket.on ('disconnect ',)={ console . log(' disconnect from server ');});为了突出websocket的作用,在html代码中,我只使用一个textarea标签来显示内容,并使用两个input标签来发送。使用套接字对象的发送方法,消息可以在服务器和客户端之间传输。

websocket群聊的实现

现在让我们假设一个场景,有两个用户u1和u2同时连接到服务器,那么我们如何让他们相互通信呢?实现方法很简单。当u1连接到服务器时,使用映射键值对将u1对应的套接字对象保存在服务器中。

//创建一个maplet map=new Map()用于放置用户对象;//用于记录用户数量的变量,初始化为0let userCount=0;//侦听socketserver.on ('connection ',socket={console.log('有用户连接')上的连接事件;map.set(userCount,socket);//.});同时,u2也连接到服务器,映射存储了u2对应的socket对象。现在,u1点击发送按钮向服务器发送消息。服务器收到消息后,遍历地图转发给所有socket对象,实现群聊的实时通信。

Socketserver.on ('connection ',socket={console.log('有用户连接');map.set(userCount,socket);//侦听information socket.on('message ',msg={//从客户端接收到的消息//遍历所有用户map.foreach ((value,index,arr)={ value . send(msg);});});});下面我发布了服务器的完整代码,仅供参考

const socket=require(' socket . io ');//创建一个websocket服务器,让Socket server=Socket . listen(require(' http ')。createserver ((req,resp)={//返回页面resp.end (require ('fs ')。readfilesync('。/socket test1 . html’);}).listen(9999,' localhost ',()={ console . log(' listening ');}));//创建一个maplet map=new Map()用于放置用户对象;//用于记录用户数量的变量,初始化为0let userCount=0;//侦听socketserver.on ('connection ',socket={console.log('有用户连接')上的连接事件;map.set(userCount,socket);//侦听information socket.on('message ',msg={//从客户端接收到的消息//遍历所有用户map.foreach ((value,index,arr)={ value . send(msg);});});//监控客户端socket.on的退出(' disconnect ',()={console.log '(用户已退出连接));});});

websocket私人聊天的实现

在谈私聊的实现之前,首先要找到每个用户的唯一标识符。在一般的项目开发中,我们使用用户的用户名进行识别,每个用户通过注册获得相应的用户名。将用户名保存在数据库中,并使用主键来防止重复。

实现私聊的方式有很多,这里我的实现方法如下:

(1)当用户连接时,使用map存储用户的socket port对象,存储的key是用户的socket对象,值是用户的用户名,并编写方法更新客户端列表(2)当用户的默认用户名未命名时,使用socket.emit方法在服务器上触发事件,遍历map找到对应的key。发送消息时,根据选择列表指定要发送的人。在服务器端,遍历地图,找到要发送的用户值,发送它,并将其更新到您自己的聊天框中

以上就是私聊的简单实现。

让我们看看具体的代码:

//node . jsconst socket=require(' socket . io ');//创建一个websocket服务器,让Socket server=Socket . listen(require(' http ')。createserver ((req,resp)={//返回页面resp.end (require ('fs ')。readfilesync('。/socket test1 . html’);}).listen(9999,' localhost ',()={ console . log(' listening ');}));//创建一个maplet map=new Map()用于放置用户对象;//用于记录用户数量的变量,初始化为0let userCount=0;//traverse maplet scan map=func={ try { map . foreach((value,index,arr)={func (value,index,arr));});} catch(e){ if(e . message==' break '){ return;} else { throw e;} } }//通知客户端弹出对话框让showdialog=(socket,msg)={socket.emit ('showdialog,msg);}//更新用户列表let update list=socket={ let user arr=[];scanMap((值,索引)={ if(值!=undefined){ userArr.push(值);} });socket.emit('newUser ',userArr}//侦听socketserver.on ('connection ',socket={console.log('有用户连接')上的连接事件;//初始化并存储当前套接字对象映射. set(socket,'未命名');//将用户信息写入mapsocket.on ('getuser ',user={//修改名称map.set(socket,user);scanMap((值,索引)={ updateList(索引));});});//通知所有客户端更新列表scanmap((值,索引)={updatelist(索引)};});//侦听message socket.on('message ',msg={//消息让发送方从客户端接收;//遍历所有用户scanmap ((value,index)={ if(index==socket){ sender=value;} });scanMap((value,index)={ if(msg . person==' all '){ index . send(sender ' : ' msg . msg);} else if(msg . person==value){ socket . send(sender ' : ' msg . msg);index.send(发件人' : ' msg . msg);抛出新错误(' break ');} });});//监控客户端套接字的退出。on('disconnect ',()={//用户退出并删除用户映射。set(socket,undefined)从映射中删除;//通知所有用户更新列表scanmap ((value,index)={ updatelist(index);});Console.log(“用户已退出连接”);});});客户:

!DOCTYPE html html lang=' en ' head meta charset=' UTF-8 ' title document/title/head dy文本区域名称=' id=' content ' cols=' 30 ' row=' 10 '/文本区域输入id=' write ' type=' text ' placeholder='请在此处写入内容input id=' send ' type=' button ' value=' send '/input type=' text ' id=' user '占位符=' user ' select style=' width : 100 px;size=' 2 ' name=' ' id=' userList '选项值='全部'群聊/option/select script src=' http :/socket。io/套接字。io。js /脚本脚本let send=document。getelementbyid(' send ');let write=document。getelementbyid(' write ');让内容=文档。getelementbyid(' content ');让用户=文档。getelementbyid(' user ');//用户列表让用户列表=文档。getelementbyid('用户列表');让socket=io。connect();//判断用户名是否为空让isUserEmpty=()={ if(user。value==' '){ alert('请填写用户名');返回false} else { return true} } //监听用户名变化让旧用户;用户。onbulr=()={ if(isUserEmpty()){//防止重复发射if(old USer==user。value){ return;} old USer=User . value socket . emit(' GetUSer ',user。值);} } //发送消息发送。onclick=()={ if(isUserEmpty()){让msg=write。价值;//内容。innerhtml=内容。值消息' n ';socket.send({msg:msg,person :用户列表。value });} if(select.value==''){ alert('请选择一个聊天对象');} };//接收到消息socket.on('message ',msg={ console.log('从服务器接收到的消息:' msg);//更新内容内容。innerHTMl=内容。值消息' n ';});socket.on('disconnect ',()={ console.log('与服务器断开连接');});//新用户加入聊天室socket.on('newUser ',arr={ UserList . InnerHTML=let all=document。创建元素('选项');all.innerHTML='群聊;all.setAttribute('value ',' all ');userList.appendChild(全部);//添加新用户arr.forEach((值,索引)={ console。log(' value : ' value ' index : ' index);让选项=文档。创建元素('选项');option . innerhtml=value option . setattribute(' value ',value);userList.appendChild(选项);userList.setAttribute('size ',userList。孩子们。长度);});//默认选中群聊user list . value=' all });//接收服务器需要弹出对话框的需求socket.on('showDialog ',msg={ alert(msg);});/脚本/正文/html

代码的具体我就不在详细讲解,都标有注释,由于只是用于博文,整体代码没有重构优化,大家看不懂的可以回复我,或者有什么地方错误请指出,我会及时改正。

另外在这个聊天室中,当用户刷新频率较快时,websocket会出现伪连接现象。

下面附上我的开源代码库地址,大家可以下载我的源码进行修改学习,共勉https://github.com/HaoDaWang/chat

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

更多资讯
游戏推荐
更多+