# 五.sockit.io

  • socket.io 是一个 websocket 库,包括了客户端的 js 和服务端的 nodejs,它的目标是构建可以在不同浏览器和移动设备上使用的实时应用。

# 1.socket.io 的特点

  • 易用性:socket.io 封装了服务端和客户端,使用起来非常简单方便。
  • 跨平台:socket.io 支持跨平台,这就意味着你有了更多的选择,可以在自己喜欢的平台下开发实时应用。
  • 自适应:它会自动根据浏览器从 websocket、ajax 长轮询、iframe 流等等各种方式中选择最佳的方式来实现网络实时应用,非常方便和人性化,而且支持的浏览器最低达 IE5.5。

# 2.案例一:web 聊天室

# 2.1 前端部分

  • 用 socket.io 实现一个聊天室

chat.html

index.html

# 2.2 后端部分

安装部署

  • 使用 npm 安装 socket.io
npm install socket.io
1

server.js

let express = require("express")
let app = express()
let path = require("path")
app.use(express.static(__dirname))
app.get("/", (req, res) => {
  res.sendFile(path.resolve(__dirname, "index.html"))
})
let server = require("http").createServer(app)
server.listen(8080)

//http://localhost:80
//ws://localhost:808
let io = require("socket.io")(server)
//监听客户端的连接
const SYSTEM = "系统"
const ALL_USERS = {}

io.on("connection", async (socket) => {
  let username
  let rooms = []
  socket.on("message", async (message) => {
    if (username) {
      let changeNameReg = /^changename:(.+)$/
      let changeNameResult = message.match(changeNameReg)
      let privateReg = /^@(.+) (.+)$/
      let privateResult = message.match(privateReg)
      if (changeNameResult) {
        let newName = changeNameResult[1]
        io.emit("message", {
          username: SYSTEM,
          content: `用户[${username}]改名为[${newName}]`,
          createAt: new Date(),
        })
        let oldSocket = ALL_USERS[username]
        delete ALL_USERS[username]
        username = newName
        ALL_USERS[username] = oldSocket
      } else if (privateResult) {
        let toUser = privateResult[1]
        let toContent = privateResult[2]
        let toScoket = ALL_USERS[toUser]
        if (toSocket) {
          toSocket.emit("message", {
            username,
            content: toContent,
            createAt: new Date(),
          })
        } else {
          socket.emit("message", {
            username: SYSTEM,
            content: `你想私聊的用户名${toUser}不存在`,
            createAt: new Date(),
          })
        }
      } else {
        let doc = {
          username,
          content: message,
        }

        if (rooms.length > 0) {
          rooms.forEach((room) => {
            io.in(room).emit("message", doc)
          })
        } else {
          io.emit("message", doc)
        }
      }
    } else {
      username = message
      ALL_USERS[username] = socket
      io.emit("message", {
        username: SYSTEM,
        content: `欢迎${username}加入聊天室`,
        createAt: new Date(),
      })
    }
  })
  //加入某个房间 一个客户端可以同时在多个房间内
  socket.on("join", (roomName) => {
    let index = rooms.findIndex((item) => item === roomName)
    if (index == -1) {
      socket.join(roomName)
      rooms.push(roomName)
      socket.emit("message", {
        username: SYSTEM,
        content: `你已经成功的加入到了${roomName}房间内`,
        createAt: new Date(),
      })
      socket.broadcast.to(roomName).emit("message", {
        username: SYSTEM,
        content: `${username}已经成功进入了${roomName}房间`,
        createAt: new Date(),
      })
      //告诉 客户端我已经成功的进入了某个房间
      socket.emit("joined", roomName)
    } else {
      socket.emit("message", {
        username: SYSTEM,
        content: `别闹!你已经在这个房间内了`,
        createAt: new Date(),
      })
    }
  })
  //离开某个房间
  socket.on("leave", (roomName) => {
    let index = rooms.findIndex((item) => item === roomName)
    if (index == -1) {
      socket.emit("message", {
        username: SYSTEM,
        content: `别闹!你根本就不在这个房间内`,
        createAt: new Date(),
      })
    } else {
      socket.leave(roomName)
      rooms.splice(index, 1)
      socket.emit("message", {
        username: SYSTEM,
        content: `你已经成功的离开了${roomName}房间`,
        createAt: new Date(),
      })

      socket.broadcast.to(roomName).emit("message", {
        username: SYSTEM,
        content: `${username}已经成功的离开了${roomName}房间`,
        createAt: new Date(),
      })

      socket.emit("leaved", roomName)
    }
  })

  socket.on("getAllMessages", async () => {
    // let messages=await Message.find().sort({createAt:-1}.limit(20));
    // messages.reverse();
    let message = { msg: "ok" }
    socket.emit("allMessages", messages)
  })

  socket.on("room", (roomName) => {
    let sockets = io.sockets.adapter.rooms[roomName].sockets
    let count = Object.keys(sockets)
  })
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144