WebSocket实现一个聊天室

相关参考:

阮一峰老师:WebSocket 教程

MDN:WebSocket

简书:nodejs-websocket介绍

一、WebSocket 介绍

WebSocket 协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工( full-duplex)通信一一允许服务器主动发送信息给客户端。

websockets是一种持久协议,http是非持久协议

现在很多网站都有实时推送的需求,比如聊天,客服咨询等。

早期没有 WebSocket 时,通过AJAX轮询(不停发送请求,询问是否有新消息),由于http请求本身的限制,服务器无法给浏览器主动发送数据,因此需要浏览器定时的给服务器发送请求(如1s-次),服务器把最新的数据响应给浏览器。这种模式的缺点就是浪费性能和资源。

在这里插入图片描述

二、WebSocket 基本使用

2.1 创建一个 WebSocket

在H5当中已经提供了 WebSocket 的 API,我们可以直接使用

语法:

var aWebSocket = new WebSocket(url [, protocols]);

url:要连接的URL;这应该是WebSocket服务器将响应的URL。

protocols 可选:
        一个协议字符串或者一个包含协议字符串的数组。这些字符串用于指定子协议,这样单个服务器可以实现多个WebSocket子协议(例如,您可能希望一台服务器能够根据指定的协议(protocol)处理不同类型的交互)。如果不指定协议字符串,则假定为空字符串。

2.2 常用事件

使用 addEventListener() 或将一个事件监听器赋值给本接口的 WebSocket对象来监听下面的事件。

事件名称事件描述
open连接成功时触发。也可以通过 onopen 属性来设置。
message收到数据时触发。也可以通过 onmessage 属性来设置。
close连接被关闭时触发。也可以通过 onclose 属性来设置。
error连接因错误而关闭时触发,例如无法发送数据时。也可以通过 onerror 属性来设置.
// 创建一个 WebSocket 连接
const socket = new WebSocket('ws://localhost:8080');

// 连接成功
socket.addEventListener('open', (event) => {
  socket.send('Hello Server!');
});

// 监听消息
socket.addEventListener('message', function (event) {
    console.log('Message from server ', event);
});

// 关闭连接
socket.addEventListener('close', (event) => {
  console.log('The connection has been closed successfully.');
)};

// 监听可能发生的错误
socket.addEventListener('error', function (event) {
  console.log('WebSocket error: ', event);
});

2.3 常用方法

方法名方法描述
WebSocket.send(data)发送数据(排队发送)
WebSocket.close([code[, reason]])关闭当前链接。
// 发送数据
button.addEventListener('click',function() {
  let value = input.value 
  socket.send('Hello Wolrd:'+value)
})

2.4 小案例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    div {
      width: 200px;
      height: 200px;
      border: 1px solid black;
    }
  </style>
</head>
<body>
  <input type="text" placeholder="输入你的内容">
  <button>发送请求</button>
  <!-- 显示结果 -->
  <div></div>
  
  <script>
    const input = document.querySelector('input')
    const button = document.querySelector('button')
    const div = document.querySelector('div')

    // 1.创建websocket
    // 参数:WebSocket(url [, protocols]);
    const socket = new WebSocket('wss://echo.websocket.org')

    // 2. open:当和 websocket服务连接成功的时候触发
    socket.addEventListener('open', function () {
      div.innerHTML = '连接成功~'
    })

    // 3.主动给 websocket服务发送消息
    button.addEventListener('click', function () {
      let value = input.value
      socket.send(value)
    })

    // 4. message:收到服务器返回的数据触发
    socket.addEventListener('message', function (event) {
      console.log(event.data);
      div.innerHTML = event.data
    })

    // 5.close:服务已断开
    socket.addEventListener('close', function () {
      div.innerHTML = '服务已断开~'
    })
  </script>
</body>
</html>

三、使用 nodejs 搭建一个 WebSocket服务器

3.1 安装 nodejs-websocket

nodejs-websocket 是一个非常方便的 websocket 依赖

这里不做过多介绍,有关使用方式:
GItHub地址:Nodejs Websocket
简书:Nodejs -websocket介绍

npm install -g nodejs-websocket

3.2 简陋版聊天室

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <input type="text" placeholder="输入你的内容">
  <button>发送请求</button>
  <!-- 显示结果 -->
  <div></div>
  <script>
    const input = document.querySelector('input')
    const button = document.querySelector('button')
    const div = document.querySelector('div')
    
    const TYPE_ENTER = 0
    const TYPE_LEAVE = 1
    const TYPE_MSG = 2

    // 1.创建websocket
    // 参数:WebSocket(url [, protocols]);
    const socket = new WebSocket('ws://127.0.0.1:8000')

    // 2. open:当和 websocket服务连接成功的时候触发
    socket.addEventListener('open', function () {
      div.innerHTML = '连接成功~'
    })

    // 3.主动给 websocket服务发送消息
    button.addEventListener('click', function () {
      let value = input.value
      socket.send(value)
      input.value = ''
    })

    // 4. message:收到服务器返回的数据触发
    socket.addEventListener('message', function (event) {
      let result = JSON.parse(event.data)
      console.log(result);

      let newDiv = document.createElement('div')
      newDiv.innerHTML = result.msg + '-----' + result.time
      if (result.type === TYPE_ENTER) {
        newDiv.style.color = 'green'
      } else if (result.type === TYPE_LEAVE) {
        newDiv.style.color = 'red'
      } else {
        newDiv.style.color = 'black'
      }
      div.appendChild(newDiv)
    })

    // 5.close:服务已断开
    socket.addEventListener('close', function () {
      div.innerHTML = '服务已断开~'
    })
  </script>
</body>
</html>

app.js

const { connect } = require('http2');
const { findSourceMap } = require('module');
const ws = require('nodejs-websocket')

const TYPE_ENTER = 0
const TYPE_LEAVE = 1
const TYPE_MSG = 2
/*    type:消息的类型      0:进入      1:离开      2:正常message  */

// 记录当前连接上来的用户数量
let count = 0

// connect 代表每个连接到服务器的用户,都会有一个connect对象
const server = ws.createServer(connect => {
  console.log('新的连接');
  count++
  connect.userName = `用户${count}`

  // 1.告诉所有用户,有人加入了聊天室
  broadcast({
    type: TYPE_ENTER,
    msg: `${connect.userName}进入了聊天室`,
    time: new Date().toLocaleTimeString()
  })

  // 每当接受到用户传递数据过来(客户端的send方法),text事件就会被触发
  connect.on('text', data => {
    // 2.当我们接收到某个用户的数据,广播给所有用户
    console.log('接受到数据:' + data);
    broadcast({
      type: TYPE_MSG,
      msg: connect.userName + ":" + data,
      time: new Date().toLocaleTimeString()
    })
  })

  // 关闭连接时触发
  connect.on('close', data => {
    console.log('关闭连接');
    
    // 3.有人离开了,广播给所有用户
    count--
    broadcast({
      type: TYPE_LEAVE,
      msg: `${connect.userName}离开了聊天室`,
      time: new Date().toLocaleTimeString()
    })
  })
  // 发生异常
  connect.on('error', data => {
    console.log("发生异常");
  })
})

// 广播,给所有的用户发送消息  connections(这个数组里,保存了每个连接)
function broadcast(msg) {
  server.connections.forEach(connect => {
    connect.send(JSON.stringify(msg))
  })
}

server.listen(8000, () => {
  console.log('Server started Complete: ws://127.0.0.1:8000');
})

效果:

在这里插入图片描述
在这里插入图片描述

四、 服务端手动搭建 WebSocket 服务器流程

在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

优雅哥cc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值