一、前言

思考要做一个聊天室,该如何去做。
现有一个聊天室,其中有张三、李四、王五这三人在里面。
张三发送一条消息,李四和王五要接收到这条消息。如何接收?
张三是直接发送给李四和王五的么?不是,而是发送消息给服务器

早期的实现方式:

客户端A将消息发送给服务器 (setMessage)。客户端B去找服务器要消息 (getMessage) 客户端B不知道该什么时候去向服务器要消息,所以会做一个定时器每隔一段时间就去找服务器要消息 这种实现方式叫做 轮询。

轮询方式存在的问题:

  1. 服务器压力山大
  2. 实时性不高

长连接的 socket 实现方式:

socket 是实现客户端与服务端双向通信的一种技术。

双向通信:客户端与服务端在第一次建立起连接之后,不会主动去断掉。并且 除了可以客服端主动向服务器发消息之外,服务端也可以主动去给客服端发消息

客户端A \ B \ C 都与服务器建立了 socket 连接 客户端A向服务器发送一条消息。服务器收到消息之后可以立马给客户端B与客服端C去发消息。

socket 除了用于聊天室还能在那些场景适用

  1. 股票交易
  2. 聊天室
  3. 实时图表更新

二、ws 模块实现

1. 后端实现

  1. 安装 ws
  1. $ npm install ws
  1. 示例代码
  1. // 引入 ws 模块
  2. const WebSocket = require('ws')
  3. // 创建 WebSocket 服务
  4. const wss = new WebSocket.Server({
  5. port: 3000, // 设置服务监听的端口号
  6. })
  7. // 监听连接建立
  8. wss.on('connection', (socket) => {
  9. // socket 连接实例
  10. // 监听客户端发来的消息
  11. socket.on('message', (message) => {
  12. })
  13. // 给客户端发送消息
  14. socket.send('消息内容')
  15. })

2. 前端实现

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <script>
  11. // 建立连接
  12. const socket = new WebSocket('ws://localhost:8080')
  13. // 连接成功
  14. socket.onopen = function () {
  15. console.log('连接成功')
  16. }
  17. // 监听服务端发来的消息
  18. socket.onmessage = function (event) {
  19. console.log(event.data)
  20. }
  21. // 给服务端发送消息
  22. socket.send('hello')
  23. </script>
  24. </body>
  25. </html>

三、socket.io 实现

1. 后端实现

  1. 安装 socket.io
  1. $ npm install socket.io
  1. 代码示例
  1. // 引入 express
  2. const express = require("express");
  3. // 引入 socketIo
  4. const socketIo = require("socket.io");
  5. // 生成 express 实例
  6. const app = express();
  7. // 生成 服务
  8. const server = app.listen(3000);
  9. // socket.io 监听服务
  10. const io = socketIo.listen(server);
  11. // socket 连接
  12. io.on("connection", socket => {
  13. // 监听客户端发来的消息
  14. socket.on("message", data => {
  15. console.log(data);
  16. });
  17. // 给自己会消息
  18. socket.emit("message", {
  19. message: "hello"
  20. });
  21. // 给其它用户广播
  22. socket.broadcast.emit("message", {
  23. message: "hello"
  24. });
  25. });

2. 前端实现

需要安装客户端连接浏览器的插件:
npm i scoket.io-client

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>Document</title>
  7. </head>
  8. <body>
  9. <script src="./socket.io.js"></script>
  10. <script>
  11. // 建立连接
  12. const socket = io('http://localhost:3000')
  13. // 连接成功
  14. socket.on('connect', () => {
  15. console.log('连接成功')
  16. })
  17. // 监听服务端发来的消息
  18. socket.on('message', (data) => {
  19. console.log(data)
  20. })
  21. // 给服务端发送消息
  22. socket.emit('message', '我的天')
  23. </script>
  24. </body>
  25. </html>