immerse
友情指路

websocket开发聊天室

2022-04-19 杂谈
Word count: 1.3k | Reading time: 5min

前言

本篇主要致力于开发一个简单的聊天室项目(纯手打),现在进行开源(未部署),主要记录一些代码注释,未来有兴趣会继续优化

介绍websocket服务

开发聊天室,我们需要用到WebSocket这个网络通信协议,那么为什么会用到它呢?初次接触 WebSocket 的人,都会问同样的问题:我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处?答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起。举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用”轮询”:每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。因此,工程师们一直在思考,有没有更好的方法。WebSocket 就是这样发明的。

前端代码(含注释)

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/* div{
width: 200px;
height: 200px;
border: 1px solid #000;
} */
</style>
</head>
<body>
<!--输入内容-->
<input type="text" placeholder="输入内容">

<!-- 发送请求-->
<button>发送消息</button>
<!--显示结果-->
<div></div>

<script>
var input = document.querySelector('input')
var button = document.querySelector('button')
var div = document.querySelector('div')
const TYPE_ENTER = 0
const TYPE_LEAVE = 1
const TYPE_MSG = 2

// 演示websocket
// h5提供了websocket的API

// 1.创建websocket
// 参数1: websocket的服务地址
var socket = new WebSocket('ws://localhost:3000')

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

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

// 4.接收websocket服务数据
socket.addEventListener('message',function(e) {
//console.log(e.data) div.innerHTML = e.data会把消息覆盖掉
var data = JSON.parse(e.data)
var dv = document.createElement('div')
dv.innerText = data.msg + '-----'+ data.time
if (data.type === TYPE_ENTER) {
dv.style.color = 'green'
} else if (data.type === TYPE_LEAVE) {
dv.style.color = 'red'
} else {
dv.style.color = 'pink'
}
div.appendChild(dv)
})

socket.addEventListener('close',function() {
div.innerHTML = '服务断开连接'
})
</script>

</body>
</html>

js代码(含注释)

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
// 1.导入nodejs-websocket包
const { time } = require('console')
const ws = require('nodejs-websocket')
const TYPE_ENTER = 0
const TYPE_LEAVE = 1
const TYPE_MSG = 2

/*

消息不应该是简单的字符串,消息应该是一个对象
type 消息的类型:0:用户进入聊天室的消息 1:用户离开聊天室的消息 2:正常的聊天消息
msg 消息的内容
time 聊天的时间

*/


// 2.记录连接的用户数量
let count = 0

const PORT = 3000
// 3.创建server
// 3.1 处理用户请求
// 3.2 每次只要有用户连接,函数就会被执行,会给当前连接的用户创建一个connect对象
const server = ws.createServer(connect => {
console.log('有用户连接')
count++
// 4.给用户起名
connect.userName = `用户${count}`
// 5.告诉所有用户有人加入聊天室
//broadcast(`${connect.userName}进入聊天室`)
broadcast({
type: TYPE_ENTER,
msg: `${connect.userName}进入聊天室`,
time: new Date().toLocaleTimeString()
})


// 6.每当接收到用户传递的数据,这个text事件就会触发
connect.on('text', data => {

// 6.1 接收用户信息的时候,告诉所有用户发送的消息
//broadcast(data)
broadcast({
type: TYPE_MSG,
msg : data,
time: new Date().toLocaleTimeString()
})
console.log('接收到了用户的数据', data)

// 7.给用户一个响应的数据
connect.send(data)
})

// 8.只要websocket连接断开, close事件就会触发
// 9.关闭连接的时候触发
connect.on('close', () => {
console.log('连接断开')
count--

// 10.告诉所有用户有人离开聊天室
//broadcast(`${connect.userName}离开聊天室`)
broadcast({
type: TYPE_LEAVE,
msg : `${connect.userName}离开聊天室`,
time: new Date().toLocaleTimeString()
})
})

// 注册error,处理用户的错误信息
connect.on('error', data => {
console.log('用户连接异常')
})
})

// 给所有用户发送消息
function broadcast(msg){
// server.connections表示所有用户
server.connections.forEach(item => {
//将对象转换成字符串
item.send(JSON.stringify(msg))
})
}

server.listen(PORT, () => {
console.log('服务启动成功,端口监听' + PORT)
})

启动服务

1
node .\app.js

实机效果

效果1.jpg

效果2.jpg

Author: immerse

Link: http://example.com/2022/04/19/websocket%E5%BC%80%E5%8F%91%E8%81%8A%E5%A4%A9%E5%AE%A4/

Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.

NextPost >
pwn日记簿--出题篇
CATALOG
  1. 1. 前言
  2. 2. 介绍websocket服务
  3. 3. 前端代码(含注释)
  4. 4. js代码(含注释)
  5. 5. 启动服务
  6. 6. 实机效果