一、WebSocket 基础概念
1. 什么是 WebSocket?
WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它允许服务端主动向客户端推送数据,实现了真正的双向实时通信。
2. WebSocket 的特点
- 全双工通信:客户端和服务器可以同时发送和接收数据
- 低延迟:相比 HTTP 轮询,减少了不必要的网络流量和延迟
- 持久连接:建立连接后保持打开状态,直到被显式关闭
- 轻量级:数据帧头部较小,减少了传输开销
3. WebSocket 与 HTTP 的区别
特性 | WebSocket | HTTP |
---|---|---|
连接方式 | 持久连接 | 短连接(请求-响应后断开) |
通信方向 | 双向 | 单向(客户端发起) |
协议标识 | ws:// 或 wss:// | http:// 或 https:// |
数据格式 | 二进制帧或文本帧 | 文本格式 |
适用场景 | 实时应用(聊天、游戏、股票等) | 传统网页请求 |
二、WebSocket 基本用法
1. 创建 WebSocket 连接
javascript
const socket = new WebSocket('ws://example.com/socket');
2. WebSocket 事件
javascript
// 连接建立
socket.onopen = (event) => {
console.log('连接已建立', event);
};
// 接收消息
socket.onmessage = (event) => {
console.log('收到消息:', event.data);
};
// 连接关闭
socket.onclose = (event) => {
console.log('连接关闭', event);
};
// 错误处理
socket.onerror = (error) => {
console.error('WebSocket错误:', error);
};
3. WebSocket 方法
javascript
// 发送消息
socket.send('Hello Server!');
// 关闭连接
socket.close();
三、在 Vue 中使用 WebSocket
1. 基本集成方式
在 Vue 组件中使用
javascript
export default {
data() {
return {
socket: null,
messages: []
}
},
mounted() {
this.initWebSocket();
},
beforeDestroy() {
this.socket.close();
},
methods: {
initWebSocket() {
this.socket = new WebSocket('wss://example.com/socket');
this.socket.onopen = () => {
console.log('连接已建立');
this.socket.send('连接初始化');
};
this.socket.onmessage = (event) => {
this.messages.push(event.data);
};
this.socket.onclose = () => {
console.log('连接已关闭');
};
},
sendMessage(message) {
if (this.socket.readyState === WebSocket.OPEN) {
this.socket.send(message);
}
}
}
}
在模板中使用
javascript
<template>
<div>
<div v-for="(msg, index) in messages" :key="index">{{ msg }}</div>
<input v-model="inputMsg" @keyup.enter="sendMessage(inputMsg)" />
</div>
</template>
2. 使用 Vue 插件封装
创建 WebSocket 插件
javascript
// websocket-plugin.js
export default {
install(Vue, options) {
const socket = new WebSocket(options.url);
Vue.prototype.$socket = socket;
socket.onmessage = (event) => {
Vue.prototype.$emit('websocket:message', event.data);
};
socket.onclose = () => {
Vue.prototype.$emit('websocket:close');
};
}
}
在 main.js 中使用
javascript
import WebSocketPlugin from './websocket-plugin';
Vue.use(WebSocketPlugin, {
url: 'wss://example.com/socket'
});
在组件中使用插件
export default {
mounted() {
this.$on('websocket:message', this.handleMessage);
},
methods: {
handleMessage(data) {
console.log('收到消息:', data);
},
send(data) {
this.$socket.send(data);
}
}
}
3. 使用 Vuex 管理 WebSocket 状态
Vuex 模块
javascript
// store/modules/websocket.js
export default {
state: {
socket: null,
messages: [],
status: 'disconnected'
},
mutations: {
SOCKET_CONNECT(state, socket) {
state.socket = socket;
state.status = 'connected';
},
SOCKET_DISCONNECT(state) {
state.status = 'disconnected';
},
SOCKET_MESSAGE(state, message) {
state.messages.push(message);
}
},
actions: {
connect({ commit }) {
const socket = new WebSocket('wss://example.com/socket');
socket.onopen = () => {
commit('SOCKET_CONNECT', socket);
};
socket.onmessage = (event) => {
commit('SOCKET_MESSAGE', event.data);
};
socket.onclose = () => {
commit('SOCKET_DISCONNECT');
};
},
send({ state }, message) {
if (state.socket && state.socket.readyState === WebSocket.OPEN) {
state.socket.send(message);
}
}
}
}
在组件中使用
javascript
export default {
computed: {
messages() {
return this.$store.state.websocket.messages;
}
},
mounted() {
this.$store.dispatch('websocket/connect');
},
methods: {
sendMessage(message) {
this.$store.dispatch('websocket/send', message);
}
}
}
四、WebSocket 最佳实践
1. 连接管理
自动重连机制:
javascript
function connect() {
const socket = new WebSocket('wss://example.com/socket');
socket.onclose = () => {
setTimeout(() => connect(), 5000); // 5秒后重连
};
return socket;
}
心跳检测:
javascript
setInterval(() => {
if (socket.readyState === WebSocket.OPEN) {
socket.send('ping');
}
}, 30000); // 每30秒发送一次心跳
2. 错误处理
javascript
socket.onerror = (error) => {
console.error('WebSocket错误:', error);
// 根据错误类型执行不同的恢复逻辑
};
3. 数据格式
建议使用 JSON 格式进行数据交换:
javascript
// 发送
socket.send(JSON.stringify({
type: 'message',
data: 'Hello'
}));
// 接收
socket.onmessage = (event) => {
const message = JSON.parse(event.data);
switch (message.type) {
case 'message':
console.log('消息:', message.data);
break;
case 'notification':
console.log('通知:', message.data);
break;
}
};
4. 安全性
始终使用 wss:// (WebSocket Secure) 而不是 ws://
实现身份验证机制(如 JWT)
限制消息大小防止 DDoS 攻击
五、常见 WebSocket 库
1. Socket.IO
javascript
import io from 'socket.io-client';
const socket = io('https://example.com');
// Vue 组件中使用
export default {
mounted() {
socket.on('chat message', (msg) => {
console.log(msg);
});
},
methods: {
sendMessage() {
socket.emit('chat message', 'Hello');
}
}
}
2. SockJS
javascript
import SockJS from 'sockjs-client';
import Stomp from 'stompjs';
const socket = new SockJS('/ws');
const stompClient = Stomp.over(socket);
stompClient.connect({}, () => {
stompClient.subscribe('/topic/messages', (message) => {
console.log(JSON.parse(message.body));
});
});
六、WebSocket 应用场景
实时聊天应用
多人协作编辑
股票/加密货币行情
在线游戏
实时监控系统
IoT 设备控制
在线教育平台
七、总结
在 Vue 中使用 WebSocket 可以通过多种方式实现:
直接在组件中管理:适合简单应用
封装为插件:便于全局使用和事件管理
结合 Vuex:适合复杂状态管理
最佳实践包括:
实现自动重连和心跳机制
使用 JSON 格式进行数据交换
注意安全性(使用 wss 和身份验证)
合理处理错误和连接状态