写点什么

使用 Socket.io 库制作一个简单的实时聊天室

  • 2022-11-07
    广东
  • 本文字数:2706 字

    阅读完需:约 9 分钟

使用Socket.io库制作一个简单的实时聊天室

WebSocket 介绍

传统的 http,在客户端没发送请求给服务器之前是不会有响应的,客户端发送请求后服务器才作出响应,明显是单向的,如果要持续获取资源就得不断重复请求



后来就有了长轮询(Long polling)的方法,客户端让 HTTP 请求保持一段时间,即使没有数据的时候也得保持连接。再后来,就有了 WebSocket


WebSocket 是专门设计来做实时应用的协议,WebSocket 和 HTTP 很像,WebSocket 请求的 URL 用的是 ws 或者 wss,在 HTTP 协议里对应 HTTP 和 HTPPS


客户端如果要发起 WebSocket 请求,需要在请求首部里作出说明,Connection 的值写成 Upgrade,Upgrade 的值写成 WebSocket,服务器收到请求后会看到连接要求升级,升级成什么在 Upgrade 里找,于是服务器就知道客户端要建立 WebSocket 连接,建立连接后就可以传输数据了


WebSocket 建立连接

我们用 node.js 来生成服务器,首先npm init -y初始化,然后安装 Websocket 依赖npm i ws,创建一个server.js作为服务器文件



在 service 里引入安装的模块,生成一个 WebSocket 实例并指名使用的端口


const WebSocket=require('ws')const wss=new WebSocket.Server({port:3000})
复制代码


加入事件操作,有人连接进来的时候使用connection来指明这个状态,并用 wx 参数表示不同的单一连接,有人退出的话要在单一连接中进行,也就是使用 wx 参数指明close状态的时候


wss.on('connection',ws=>{  console.log('有人连接进来');
ws.on('close',()=>{ console.log('有人退出了'); })})
复制代码


测试一下,但是现在直接用浏览器访问服务器是没有效果的,因为浏览器是使用 HTTP 访问的,不会告诉服务器用 WebSocket 连接,所以还需要创建一个 index.html 文件,在 html 文件里面成一个 WebSocket 实例,参数里填写 URL,因为是在开发所以直接使用 ws,实例应用中一般是 wss,是安全版的 ws


const ws=new WebSocket('ws://localhost:3000')
ws.addEventListener('open',()=>{//ws实例事件监听函数 console.log('连接上服务器了'); ws.send('12345,')})
复制代码


node server.js 运行服务器,然后运行 index.html,打开页面前端和后端的控制台都有提示了,关闭页面也会有提示,也就是断开连接,WebSocket 的连接功能也就实现了





不过还缺少了数据传输功能,还是在单一连接里进行操作,如果收到 message 就把客户端的信息处理一下返回给客户端。客户端也需要设置在连接上就马上发送信息给服务器并监听 message 事件,有数据就在控制台输出返回的数据


//服务器ws.on('message',data=>{//接收到数据就把数据加工一下返回给客户端    ws.send(data+'今晚打老虎')})//客户端ws.addEventListener('open',()=>{  console.log('连接上服务器了');  ws.send('12345,')//连上服务器就发送数据给服务器})ws.addEventListener('message',({data})=>{//接收服务器返回的数据  console.log(data);})
复制代码


刷新页面,可以看到控制台打印的消息无误就代表实现了数据传输


Socket.io 库

Socket.io 库也有用到 WebSocket 协议,但是对不支持 WebSocket 的浏览器会回退到 HTTP 轮询,还提供自动重连,是一个更高级的库,有了 WebSocket 的基础就可以使用 Socket.io 实现一个简单的实时聊天应用


还是和上面操作大致一样,初始化,npm i express socket.io安装 express 和 socket.io 依赖,创建 server.js 和 index.html


先用安装好的 express 库生成一个实例 app 再调用 http 模块,并使用 app 实例生成一个服务器实例,也就是基于 http 模块生成服务器实例,写起来更方便一些


const app=require('express')()//生成app实例const server=require('http').createServer(app)//生成服务器实例
复制代码


当接收到请求的时候,把 html 文件作为响应的文件


app.get('/',(req,res)=>{  res.sendFile(__dirname+'/index.html')//__dirname绝对路径})
复制代码


html 代码,主要有 input 输入框和按钮,聊天内容就放在 ul 标签里




注意服务器不能直接用 app.listen,不然还是使用 HTTP 进行交互,使用刚刚创建的 server 实例创建一个 socket.io 实例,使用 service 实例监听端口


const server=require('http').createServer(app)//生成服务器实例const {Server}=require('socket.io')//导入模块const io=new Server(server)创建io实例
server.listen('3000',()=>'服务器开启')//监听3000端口
复制代码


和之前 WebSocket 连接操作很类似,有人连接进来的时候使用connection来指明这个状态并用 socket 参数表示不同的单一连接,有人退出的话要在单一连接中进行,也就是使用 socket 参数指明disconnect状态的时候


io.on('connection',socket=>{  console.log('有人进入聊天室');
socket.on('disconnect',()=>{ console.log('有人离开聊天室'); })})
复制代码


客户端也要作出相应的连接,和刚刚 WebSocket 不同的是,因为这是服务器响应文件,可以直接在 script 标签里指定路径,这样可以调用到 io 函数


///socket.io/socket.io.js服务器响应文件,自动生成<script src="/socket.io/socket.io.js"></script><script>    const socket=io()</script>
复制代码


运行服务器,在浏览器里访问 localhost:3000,可以看到服务器控制台有提示,代表连接成功了,关掉浏览器页面服务器也有提示,代表断开连接了



连接成功就可以来实现实时消息的功能了,服务端在 socket 连接的时候开启chat message事件,客户端先获取 form 和 input 两个元素,并且监听 form 的有提交动作的时候,先取消防止默认刷新事件,输入框有内容的时候触发 chat message 事件传入输入框的内容,然后清空一下输入框


//服务端socket.on('chat message',msg=>{    console.log(msg);})//客户端const form=document.querySelector('form')const input=document.querySelector('input')
form.addEventListener('submit',e=>{ e.preventDefault()//取消事件默认动作 if(input.value){ socket.emit('chat message' , input.value)//触发chat message事件并传入输入框里的值 input.value='' }})
复制代码


重启一下服务器,在浏览器里访问 localhost:3000,在输入框里输入值点击发送按钮触发chat message事件将值传给服务器




服务器收到后还得广播给所有人,这样才能更新聊天室的内容,在chat message事件下用 io 这个实例触发一下 chat message,并且把从客户端收到的数据发送出去


socket.on('chat message',msg=>{    io.emit('chat message',msg)})
复制代码


客户端获取一下 ul 元素,使用 socket 实例监听chat message事件,服务器发来数据就生成新的 li 元素,把数据内容放进 li 元素里面,然后使用 appendChild 为 ul 新增子元素 li


socket.on('chat message',msg=>{  const li =document.createElement('li')//创建新元素  li.textContent=msg  ul.appendChild(li)//新增子元素})
复制代码


服务器重启之后打开多个页面输入消息,其他页面也会有同步的消息,也就实现了实时聊天室了



发布于: 刚刚阅读数: 3
用户头像

还未添加个人签名 2022-11-01 加入

还未添加个人简介

评论

发布
暂无评论
使用Socket.io库制作一个简单的实时聊天室_JavaScript_格斗家不爱在外太空沉思_InfoQ写作社区