# 离线消息缓存发送

客户端:

  • 设置uid,确定ws唯一的标识
  • 断线重连后,发送roomid与uid
const urlParams = new URLSearchParams(window.location.search)
  const uid = urlParams.get("uid")
  if (this.name.trim() === "") {
  alert("用户名不得为空")
  return
}
this.wsHandle.send(
  JSON.stringify({
    name: this.name,
    roomid: this.roomid,
    uid: uid,
    event: "login",
  })
)
this.isShow = false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

服务端:

  • 使用redis进行消息的缓存
  • 对客户端的连接进行唯一性标识
  • 对于断开连接的客户端,离线消息进行保存
  • 再次连接过来的客户端,发送离线消息
wss.on("connection", function(ws, req) {
  // 初始化客户端的连接状态量
  ws.isAlive = true

  // console.log('a new client is connected!');
  ws.on("message", async function(msg) {
    var msgObj = JSON.parse(msg)
    if (msgObj.event === "heartbeat" && msgObj.message === "pong") {
      ws.isAlive = true
      return
    }
    if (msgObj.name) {
      ws.name = msgObj.name
    }
    if (msgObj.uid) {
      ws.uid = msgObj.uid
    }
    if (typeof ws.roomid === "undefined" && msgObj.roomid) {
      // 还需要一个客户端的标识,可以知道ws给谁去发送消息
      ws.roomid = msgObj.roomid
      const result = await existKey(prefix + msgObj.roomid)
      if (result === 0) {
        // 初始化数据
        setValue(prefix + msgObj.roomid, ws.uid)
      } else {
        let arrStr = await getValue(prefix + msgObj.roomid)
        // String -> Json
        let arr = arrStr.split(",")
        if (arr.indexOf(ws.uid) === -1) {
          arrStr += "," + ws.uid
          setValue(prefix + msgObj.roomid, arrStr)
        }
      }
    }
    // 广播到其他的客户端
    let arrStr1 = await getValue(prefix + ws.roomid)
    let arr1 = arrStr1.split(",")
    // 在线人数,计算uid的个数
    msgObj.total = arr1.length
    msgObj.num = wss.clients.size
    wss.clients.forEach(async function each(client) {
      if (client.readyState === WebSocket.OPEN && client.roomid === ws.roomid) {
        client.send(JSON.stringify(msgObj))
        // 删除已经发送了消息的对应的对象
        if (arr1.indexOf(client.uid) !== -1) {
          arr1.splice(arr1.indexOf(client.uid), 1)
        }
        let result = await existKey(ws.uid)
        if (result !== 0) {
          let tmpArr = await getValue(ws.uid)
          let tmpObj = JSON.parse(tmpArr)
          let uid = ws.uid
          if (tmpObj.length > 0) {
            let i = []
            // 遍历数组,判断是否是同一个roomid,否则的话,就保存数据
            tmpObj.forEach(function(item) {
              if (item.roomid === client.roomid && uid === client.uid) {
                // 如果是同一个roomid,就发送对应的消息数据。
                client.send(JSON.stringify(item.msg))
                i.push(item)
              }
            })
            if (i.length > 0) {
              i.forEach(function(item) {
                tmpObj.splice(item, 1)
              })
            }
            setValue(ws.uid, JSON.stringify(tmpObj))
          }
        }
      }
      // 判断,是否有客户端没有连接。
      // 对于没有连接的客户端的数据,进行分发缓存处理
    })

    // 说明有一些客户端断开了与roomid的连接,并且,其他客户端发送了对应的消息
    if (arr1.length > 0 && msgObj.event === "message") {
      arr1.forEach(async function(item) {
        const result = await existKey(item)
        if (result !== 0) {
          let udata = await getValue(item)
          let uObj = JSON.parse(udata)
          uObj.push({
            roomid: ws.roomid,
            msg: msgObj,
          })
          setValue(item, JSON.stringify(uObj))
        } else {
          // 说明先前,这个数据没有进行缓存 ,没有记录
          setValue(
            item,
            JSON.stringify([
              {
                roomid: ws.roomid,
                msg: msgObj,
              },
            ])
          )
        }
      })
    }
  })
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
上次更新: 2020/10/28 下午11:02:30