介绍
在现代互联网应用中,实时通信变得越来越重要。传统的 HTTP 协议在浏览器与服务器之间的通信中起着关键作用,但是它存在一些限制,特别是在实时性和双向通信方面。为了满足实时通信的需求,WebSocket 协议应运而生。
WebSocket 是一种全双工通信协议,它在浏览器和服务器之间提供了持久连接,允许双方进行实时的双向通信。与传统的 HTTP 请求/响应模式不同,WebSocket 提供了更高效的实时数据传输和事件驱动的通信方式。它通过建立一条持久的连接,避免了不必要的请求和响应的开销,实现了低延迟、高效率的实时通信。
WebSocket 与传统的 HTTP 协议对比
在实时通信领域,传统的 HTTP 协议存在以下一些问题:
- 频繁的请求和响应:每次通信都需要建立和关闭连接,带来额外的开销。
- 高延迟:每次通信都需要经过多个网络层的传输,延迟较高。
- 单向通信:HTTP 是一种单向的请求/响应模式,客户端无法主动向服务器推送数据。
我们将从连接方式、数据传输方式、通信效率、数据格式、服务器推送和适用场景等方面,对比一下websocket与http的区别
特点 | WebSocket | HTTP |
---|---|---|
连接方式 | 持久连接,通过握手建立单个连接 | 每次请求/响应建立新的连接 |
数据传输方式 | 全双工通信,客户端和服务器可以同时发送和接收数据 | 单向通信,客户端发送请求,服务器返回响应 |
通信效率 | 低延迟,实时性强,数据传输效率高 | 高延迟,每次请求都需要重新建立连接,数据传输效率较低 |
数据格式 | 支持任意格式的数据,如文本、二进制数据等 | 基于文本的格式,如HTML、JSON等 |
服务器推送 | 服务器可以主动向客户端推送消息 | 服务器无法主动向客户端推送消息,需要客户端主动发起请求 |
适用场景 | 实时通信、聊天应用、多人协作、实时数据展示等场景 | 请求/响应模式的数据交互、静态内容展示、数据查询等场景 |
实现一个简单的websocket
后端实现
后端实现WebSocket的示例代码(使用Node.js和WebSocket库):
引入ws
库,使用new WebSocket.Server
创建了一个WebSocket服务器,并监听端口8080。
// 创建WebSocket服务器
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
当有客户端连接时,会触发connection
事件,我们在message
事件中监听客户端的信息,然后通过ws.send
方法向客户端发生请求
当客户端关闭连接时,会触发close
事件。
// 监听连接事件
wss.on('connection', function(ws) {
console.log('有客户端连接'); // 监听消息事件
ws.on('message', function(message) {
console.log('收到客户端的消息:', message);
// 发送消息到客户端
ws.send('Hello Client');
});
// 监听关闭事件
ws.on('close', function() {
console.log('客户端连接已关闭');
});
});
那么在本地运行上面,访问的链接是ws://localhost:8080
,注意这里websocket的链接是ws作为协议名的,这就不同于http。
前端代码
先使用new WebSocket
创建一个websocket实例,然后通过onopen
事件与websocket
服务器建立连接
// 创建WebSocket连接
const socket = new WebSocket('ws://localhost:8080');
// 建立连接事件
socket.onopen = function() {
console.log('WebSocket连接已建立');
// 向服务器发送消息
socket.send('Hello, server!');
};
然后通过onmessage
,onclose
,onerror
事件,分别监听服务器发来的消息,连接关闭,错误事件
// 监听接收到服务器消息的事件
socket.onmessage = function(event) {
const message = event.data;
console.log('接收到服务器消息:', message);
};
// 监听连接关闭事件
socket.onclose = function() {
console.log('WebSocket连接已关闭');
};
// 监听连接错误事件
socket.onerror = function(error) {
console.error('WebSocket连接错误:', error);
};
好了,现在把前后端代码运行起来,我们发现前端能够正常收到服务端的数据
但是服务端收到的数据是二进制的形式,所以我们需要稍微改动一下代码。
将服务端message
事件的代表改成下面的颜值
ws.on('message', (data) => {
// 将接收到的二进制数据转换为字符串
const message = data.toString('utf8');
console.log('收到客户端的消息:', message);
ws.send('Hello Client');
});
我们再运行一下代码,就发现能够正常输出内容了
总结一下前后端常用的websocket的方法
后端API:
方法 | 描述 |
---|---|
ws.on('connection') |
当客户端与服务器建立 WebSocket 连接时触发的事件。 |
ws.on('message') |
当服务器接收到来自客户端的消息时触发的事件。 |
ws.on('close') |
当 WebSocket 连接关闭时触发的事件。 |
ws.send(data) |
向客户端发送消息,参数 data 可以是字符串或二进制数据。 |
ws.close() |
关闭 WebSocket 连接。 |
ws.clients |
存储所有连接到服务器的 WebSocket 客户端的列表。 |
前端API:
方法 | 描述 |
---|---|
new WebSocket(url) |
创建一个 WebSocket 实例,指定要连接的 WebSocket 服务器的 URL。 |
ws.onopen |
当 WebSocket 连接成功建立时触发的事件。 |
ws.onmessage |
当接收到来自 WebSocket 服务器的消息时触发的事件。 |
ws.onerror |
当 WebSocket 发生错误时触发的事件。 |
ws.onclose |
当 WebSocket 连接关闭时触发的事件。 |
ws.send(data) |
向 WebSocket 服务器发送消息,可以是字符串、ArrayBuffer 或 Blob。 |
ws.close() |
关闭 WebSocket 连接。 |
webSocket的使用场景
WebSocket可以提供实时、双向、持久的通信能力,使得 Web 应用能够实现高效、实时的数据传输和即时通信。
它适用于各种需要实时数据交互和即时通信的场景,如实时聊天应用、在线多人游戏、实时数据更新、即时通知和提醒、实时协作和协同编辑等。
简述一下WebSocket的工作原理
- 建立握手:客户端发起WebSocket连接请求,包含一些特定的头部信息,例如Upgrade和Connection字段。服务器接收到请求后,如果支持WebSocket协议,会返回一个握手响应,其中包含状态码101 Switching Protocols和一些额外的头部信息。
- 建立连接:一旦握手成功,客户端和服务器之间建立了持久连接。这个连接是基于TCP协议的,使用WebSocket协议进行通信。
- 数据传输:一旦连接建立,客户端和服务器可以通过发送消息来进行双向通信。客户端和服务器可以发送文本数据或二进制数据。数据以数据帧的形式传输,帧中包含有效负载和一些控制信息。
- 关闭连接:当客户端或服务器决定关闭连接时,它们可以发送关闭帧来表示关闭连接。收到关闭帧的一方也会发送一个关闭帧作为确认,并且双方会协商关闭连接的过程。
websocket的兼容性情况
通过can i use网址我们可以知道,WebSocket 在现代的 Web 浏览器中具有广泛的兼容性,但在一些旧版本的浏览器中可能存在兼容性问题。
WebSocket的安全性
WebSocket 本身并不提供加密功能,它是一种基于 TCP 的协议,数据是以明文形式传输的。因此,如果在使用 WebSocket 时不进行任何加密措施,那么数据在传输过程中可能会被窃听、篡改或伪造。
为了保护 WebSocket 通信的安全性,推荐使用 SSL/TLS 协议对 WebSocket 连接进行加密。通过在建立 WebSocket 连接时使用加密传输,可以确保数据在传输过程中被加密,并防止第三方窃听或篡改数据。