相关参考:
阮一峰老师:WebSocket 教程
MDN:WebSocket
文章目录
一、WebSocket 介绍
WebSocket 协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工( full-duplex)通信一一允许服务器主动发送信息给客户端。
websockets是一种持久协议,http是非持久协议
现在很多网站都有实时推送的需求,比如聊天,客服咨询等。
早期没有 WebSocket 时,通过AJAX轮询(不停发送请求,询问是否有新消息),由于http请求本身的限制,服务器无法给浏览器主动发送数据,因此需要浏览器定时的给服务器发送请求(如1s-次),服务器把最新的数据响应给浏览器。这种模式的缺点就是浪费性能和资源。
二、WebSocket 基本使用
2.1 创建一个 WebSocket
在H5当中已经提供了 WebSocket 的 API,我们可以直接使用
语法:
var aWebSocket = new WebSocket(url [, protocols]);
url:要连接的URL;这应该是WebSocket服务器将响应的URL。
protocols 可选:
一个协议字符串或者一个包含协议字符串的数组。这些字符串用于指定子协议,这样单个服务器可以实现多个WebSocket子协议(例如,您可能希望一台服务器能够根据指定的协议(protocol)处理不同类型的交互)。如果不指定协议字符串,则假定为空字符串。
2.2 常用事件
使用 addEventListener() 或将一个事件监听器赋值给本接口的 WebSocket对象来监听下面的事件。
事件名称 | 事件描述 |
---|---|
open | 连接成功时触发。也可以通过 onopen 属性来设置。 |
message | 收到数据时触发。也可以通过 onmessage 属性来设置。 |
close | 连接被关闭时触发。也可以通过 onclose 属性来设置。 |
error | 连接因错误而关闭时触发,例如无法发送数据时。也可以通过 onerror 属性来设置. |
// 创建一个 WebSocket 连接
const socket = new WebSocket('ws://localhost:8080');
// 连接成功
socket.addEventListener('open', (event) => {
socket.send('Hello Server!');
});
// 监听消息
socket.addEventListener('message', function (event) {
console.log('Message from server ', event);
});
// 关闭连接
socket.addEventListener('close', (event) => {
console.log('The connection has been closed successfully.');
)};
// 监听可能发生的错误
socket.addEventListener('error', function (event) {
console.log('WebSocket error: ', event);
});
2.3 常用方法
方法名 | 方法描述 |
---|---|
WebSocket.send(data) | 发送数据(排队发送) |
WebSocket.close([code[, reason]]) | 关闭当前链接。 |
// 发送数据
button.addEventListener('click',function() {
let value = input.value
socket.send('Hello Wolrd:'+value)
})
2.4 小案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div {
width: 200px;
height: 200px;
border: 1px solid black;
}
</style>
</head>
<body>
<input type="text" placeholder="输入你的内容">
<button>发送请求</button>
<!-- 显示结果 -->
<div></div>
<script>
const input = document.querySelector('input')
const button = document.querySelector('button')
const div = document.querySelector('div')
// 1.创建websocket
// 参数:WebSocket(url [, protocols]);
const socket = new WebSocket('wss://echo.websocket.org')
// 2. open:当和 websocket服务连接成功的时候触发
socket.addEventListener('open', function () {
div.innerHTML = '连接成功~'
})
// 3.主动给 websocket服务发送消息
button.addEventListener('click', function () {
let value = input.value
socket.send(value)
})
// 4. message:收到服务器返回的数据触发
socket.addEventListener('message', function (event) {
console.log(event.data);
div.innerHTML = event.data
})
// 5.close:服务已断开
socket.addEventListener('close', function () {
div.innerHTML = '服务已断开~'
})
</script>
</body>
</html>
三、使用 nodejs 搭建一个 WebSocket服务器
3.1 安装 nodejs-websocket
nodejs-websocket 是一个非常方便的 websocket 依赖
这里不做过多介绍,有关使用方式:
GItHub地址:Nodejs Websocket
简书:Nodejs -websocket介绍
npm install -g nodejs-websocket
3.2 简陋版聊天室
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" placeholder="输入你的内容">
<button>发送请求</button>
<!-- 显示结果 -->
<div></div>
<script>
const input = document.querySelector('input')
const button = document.querySelector('button')
const div = document.querySelector('div')
const TYPE_ENTER = 0
const TYPE_LEAVE = 1
const TYPE_MSG = 2
// 1.创建websocket
// 参数:WebSocket(url [, protocols]);
const socket = new WebSocket('ws://127.0.0.1:8000')
// 2. open:当和 websocket服务连接成功的时候触发
socket.addEventListener('open', function () {
div.innerHTML = '连接成功~'
})
// 3.主动给 websocket服务发送消息
button.addEventListener('click', function () {
let value = input.value
socket.send(value)
input.value = ''
})
// 4. message:收到服务器返回的数据触发
socket.addEventListener('message', function (event) {
let result = JSON.parse(event.data)
console.log(result);
let newDiv = document.createElement('div')
newDiv.innerHTML = result.msg + '-----' + result.time
if (result.type === TYPE_ENTER) {
newDiv.style.color = 'green'
} else if (result.type === TYPE_LEAVE) {
newDiv.style.color = 'red'
} else {
newDiv.style.color = 'black'
}
div.appendChild(newDiv)
})
// 5.close:服务已断开
socket.addEventListener('close', function () {
div.innerHTML = '服务已断开~'
})
</script>
</body>
</html>
app.js
const { connect } = require('http2');
const { findSourceMap } = require('module');
const ws = require('nodejs-websocket')
const TYPE_ENTER = 0
const TYPE_LEAVE = 1
const TYPE_MSG = 2
/* type:消息的类型 0:进入 1:离开 2:正常message */
// 记录当前连接上来的用户数量
let count = 0
// connect 代表每个连接到服务器的用户,都会有一个connect对象
const server = ws.createServer(connect => {
console.log('新的连接');
count++
connect.userName = `用户${count}`
// 1.告诉所有用户,有人加入了聊天室
broadcast({
type: TYPE_ENTER,
msg: `${connect.userName}进入了聊天室`,
time: new Date().toLocaleTimeString()
})
// 每当接受到用户传递数据过来(客户端的send方法),text事件就会被触发
connect.on('text', data => {
// 2.当我们接收到某个用户的数据,广播给所有用户
console.log('接受到数据:' + data);
broadcast({
type: TYPE_MSG,
msg: connect.userName + ":" + data,
time: new Date().toLocaleTimeString()
})
})
// 关闭连接时触发
connect.on('close', data => {
console.log('关闭连接');
// 3.有人离开了,广播给所有用户
count--
broadcast({
type: TYPE_LEAVE,
msg: `${connect.userName}离开了聊天室`,
time: new Date().toLocaleTimeString()
})
})
// 发生异常
connect.on('error', data => {
console.log("发生异常");
})
})
// 广播,给所有的用户发送消息 connections(这个数组里,保存了每个连接)
function broadcast(msg) {
server.connections.forEach(connect => {
connect.send(JSON.stringify(msg))
})
}
server.listen(8000, () => {
console.log('Server started Complete: ws://127.0.0.1:8000');
})
效果: