likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 69

WebSocket介绍

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

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

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

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

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

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

WebSocket建立连接

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

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

在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的连接功能也就实现了

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

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

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

不过还缺少了数据传输功能,还是在单一连接里进行操作,如果收到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库

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标签里

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

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

注意服务器不能直接用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.io库制作一个简单的实时聊天室

连接成功就可以来实现实时消息的功能了,服务端在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事件将值传给服务器

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

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

服务器收到后还得广播给所有人,这样才能更新聊天室的内容,在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)//新增子元素
})

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

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

转载自:https://juejin.cn/post/7158251550253514760
评论
请登录