前言:

本篇是用了nodejs-websocket来实现服务端的socket服务器的,比较偏向于原生,后面有时间再去研究socket.IO框架。这个聊天室比较简陋,只实现了最基本的功能,结构和代码都比较简单。
nodejs-websocket

1.构建websocket的node服务端

(1)安装nodejs-websocket

npm install nodejs-websocket —save

目录结构:
image.png

(2)编写服务端代码

这里直接给了,比较简单,可以直接看注释

聊天室需求: 01-能多个用户登录,每一个connect对象表示一个用户接入 02-用户进入(离开)聊天室后,系统广播用户进入(离开)聊天室 03-某个用户发言,消息传给服务器,服务器再广播给聊天室内的人 04-定义用户的三个状态,每个状态传给客户端展示不同的消息颜色: 进入聊天室为0, 退出聊天室为1, 用户发送消息为2

  1. const ws = require("nodejs-websocket")
  2. const PORT = 8080
  3. const TYPE_ENTER = 0
  4. const TYPE_EXIT = 1
  5. const TYPE_MSG = 2
  6. // 聊天室需求:
  7. // 01-能多个用户登录,每一个connect对象表示一个用户接入
  8. // 02-用户进入(离开)聊天室后,系统广播用户进入(离开)聊天室
  9. // 03-某个用户发言,消息传给服务器,服务器再广播给聊天室内的人
  10. // 04-定义用户的三个状态,每个状态传给客户端展示不同的消息颜色:
  11. // 进入聊天室为0,退出聊天室为1,用户发送消息为2
  12. // count定义为用户的数量
  13. let count = 0
  14. const server = ws.createServer((connect) => {
  15. // 新用户连接时触发
  16. {
  17. console.log("新用户连接成功");
  18. // 用户数量加一
  19. count++
  20. connect.name = `用户${count}`
  21. // 用户名最初时发给用户,后面不再发送
  22. connect.sendText(JSON.stringify({
  23. type: "name",
  24. username: connect.name
  25. }))
  26. // 用户进入聊天室了,系统广播一次
  27. let enterMsg = JSON.stringify(createMsg(TYPE_ENTER, `${connect.name}进入了聊天室`))
  28. broadcast(enterMsg)
  29. }
  30. // 当用户传入数据时,text事件会被触发
  31. connect.on("text", (msg) => {
  32. console.log("收到消息:", msg);
  33. // connect.sendText(msg)
  34. // 有用户发送消息了,广播给聊天室每一个用户
  35. let userMsg = JSON.stringify(createMsg(TYPE_MSG, `${connect.name}:${msg}`))
  36. broadcast(userMsg)
  37. })
  38. // 注册close,用户连接断开时自动触发(用户关闭页面)
  39. connect.on("close", () => {
  40. // 用户退出聊天室了,系统广播一次
  41. let exitMsg = JSON.stringify(createMsg(TYPE_EXIT, `${connect.name}退出了聊天室`))
  42. broadcast(exitMsg)
  43. console.log("连接断开啦!!!");
  44. })
  45. // 注册error,处理用户的错误信息(连接断开时会有错误处理)
  46. connect.on("error", () => {
  47. console.log("连接异常");
  48. })
  49. })
  50. // 广播函数
  51. function broadcast(msg) {
  52. server.connections.forEach(function (connect) {
  53. connect.sendText(msg)
  54. })
  55. }
  56. // 返回的消息对象
  57. function createMsg(type, content) {
  58. return {
  59. type,
  60. content,
  61. time: new Date().toLocaleDateString()
  62. }
  63. }
  64. server.listen(PORT, () => {
  65. console.log("websocket服务启动成功,监听端口:", PORT);
  66. })

2.客户端H5代码的编写

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>WebSocket</title>
  8. <style>
  9. .msg-box {
  10. width: 30rem;
  11. height: 30rem;
  12. margin-top: .5rem;
  13. padding: .5rem;
  14. border: 1px solid brown;
  15. border-radius: .5rem;
  16. font-size: 1.2rem;
  17. }
  18. </style>
  19. </head>
  20. <body>
  21. <h2 class="username"></h2>
  22. <!-- 输入消息 -->
  23. <input type="text" placeholder="输入要发送的消息" />
  24. <!-- 发送消息 -->
  25. <button class="sendMsg">发送消息</button>
  26. <!-- 退出聊天室 -->
  27. <button class="exitRoom">退出聊天室</button>
  28. <!-- 接收消息框 -->
  29. <div class="msg-box"></div>
  30. </body>
  31. <script>
  32. let username = document.querySelector(".username")
  33. let input = document.querySelector("input")
  34. let sendMsg = document.querySelector(".sendMsg")
  35. let exitRoom = document.querySelector(".exitRoom")
  36. let msgBox = document.querySelector(".msg-box")
  37. // 01-创建一个WebSocket对象(这个服务地址,你发送什么,他就返回什么)
  38. let ws = new WebSocket("ws://localhost:8080")
  39. // 02-onopen,与websocket服务器连接成功时触发
  40. ws.addEventListener('open', () => {
  41. console.log('websocket connect is open');
  42. })
  43. // 03-onmessage,监听服务器传入的数据,服务器发送消息时触发
  44. ws.addEventListener('message', (e) => {
  45. // JSON.parse反序列化后端传过来的JSON
  46. let data = JSON.parse(e.data)
  47. // 判断data.type是否是用户名
  48. if (data.type === "name") {
  49. // 是用户名,显示给用户
  50. username.innerHTML = data.username
  51. } else {
  52. // 不是用户名,则解析消息数据
  53. let { name, type, content, time } = data
  54. // 每条消息创建一个div插入到box内
  55. let newMsg = document.createElement("div")
  56. newMsg.innerHTML = `${content} - ${time}`
  57. // 判断消息的类型,来转变不同的颜色
  58. if (type === 0) {
  59. newMsg.style.color = "green"
  60. } else if (type === 1) {
  61. newMsg.style.color = "red"
  62. } else {
  63. newMsg.style.color = "skyblue"
  64. }
  65. msgBox.appendChild(newMsg)
  66. }
  67. })
  68. // 退出聊天室
  69. exitRoom.addEventListener('click', () => {
  70. // 04-close()关闭websocket连接
  71. ws.close()
  72. console.log("websocket connect is close");
  73. })
  74. // 向服务端发送信息
  75. sendMsg.addEventListener('click', () => {
  76. let value = input.value
  77. ws.send(value)
  78. console.log("发送成功");
  79. // 发送完成清空发送框
  80. input.value = null
  81. })
  82. </script>
  83. </html>

3.页面展示

用户进入房间

image.png

用户间发送消息image.png

用户退出房间

用户3和用户1分别退出房间
image.png