WebSocket提供全双工通信通道。
// WebSocket特点:
// 1. 全双工通信:客户端和服务器可以同时发送消息
// 2. 低延迟:建立连接后,通信无需HTTP开销
// 3. 持久连接:一次握手,持续通信
// 4. 二进制支持:可以发送文本和二进制数据
// 与HTTP对比
// HTTP: 请求-响应模式,单向
// WebSocket: 双向通信,实时
// 应用场景
// - 实时聊天
// - 在线游戏
// - 股票行情
// - 协作编辑
// - 实时通知
创建和管理WebSocket连接。
// 创建WebSocket连接
const ws = new WebSocket("wss://api.db-w.cn/ws");
// WebSocket URL格式
// ws://host:port/path 非加密
// wss://host:port/path 加密(推荐)
const ws = new WebSocket("wss://api.db-w.cn/ws");
// WebSocket状态
console.log(ws.readyState);
// 状态值:
// 0: CONNECTING - 连接中
// 1: OPEN - 已连接
// 2: CLOSING - 关闭中
// 3: CLOSED - 已关闭
// 检查状态
function isConnected() {
return ws.readyState === WebSocket.OPEN;
}
const ws = new WebSocket("wss://api.db-w.cn/ws");
// 连接打开
ws.onopen = function(event) {
console.log("连接已建立");
// 发送消息
ws.send("Hello Server");
};
// 连接关闭
ws.onclose = function(event) {
console.log("连接已关闭");
console.log("关闭码:", event.code);
console.log("关闭原因:", event.reason);
console.log("是否干净关闭:", event.wasClean);
};
// 连接错误
ws.onerror = function(error) {
console.error("WebSocket错误:", error);
};
发送和接收消息。
const ws = new WebSocket("wss://api.db-w.cn/ws");
ws.onopen = function() {
// 发送文本
ws.send("Hello Server");
// 发送JSON
ws.send(JSON.stringify({
type: "message",
content: "东巴文"
}));
// 发送二进制数据
const buffer = new ArrayBuffer(4);
const view = new DataView(buffer);
view.setInt32(0, 1234);
ws.send(buffer);
// 发送Blob
const blob = new Blob(["Hello"], { type: "text/plain" });
ws.send(blob);
};
const ws = new WebSocket("wss://api.db-w.cn/ws");
ws.onmessage = function(event) {
// 消息数据
console.log("收到消息:", event.data);
// 检查数据类型
if (typeof event.data === "string") {
// 文本消息
const message = JSON.parse(event.data);
console.log(message);
} else if (event.data instanceof Blob) {
// Blob数据
const reader = new FileReader();
reader.onload = function() {
console.log("Blob内容:", reader.result);
};
reader.readAsText(event.data);
} else if (event.data instanceof ArrayBuffer) {
// ArrayBuffer数据
const view = new DataView(event.data);
console.log(view.getInt32(0));
}
};
const ws = new WebSocket("wss://api.db-w.cn/ws");
// 设置二进制类型
ws.binaryType = "blob"; // 接收Blob(默认)
ws.binaryType = "arraybuffer";// 接收ArrayBuffer
ws.onmessage = function(event) {
if (event.data instanceof ArrayBuffer) {
const view = new DataView(event.data);
console.log(view.getInt32(0));
}
};
WebSocket的事件处理。
const ws = new WebSocket("wss://api.db-w.cn/ws");
// 使用addEventListener
ws.addEventListener("open", function(event) {
console.log("连接打开");
});
ws.addEventListener("message", function(event) {
console.log("收到消息:", event.data);
});
ws.addEventListener("close", function(event) {
console.log("连接关闭:", event.code, event.reason);
});
ws.addEventListener("error", function(error) {
console.error("连接错误:", error);
});
// 常见关闭码
// 1000: 正常关闭
// 1001: 端点离开
// 1002: 协议错误
// 1003: 不支持的数据类型
// 1006: 异常关闭(没有收到关闭帧)
// 1007: 数据类型不一致
// 1008: 违反策略
// 1009: 消息过大
// 1010: 缺少扩展
// 1011: 内部错误
// 1012: 服务重启
// 1013: 稍后重试
// 3000-3999: 自定义保留
// 4000-4999: 应用自定义
ws.onclose = function(event) {
switch (event.code) {
case 1000:
console.log("正常关闭");
break;
case 1006:
console.log("连接异常断开");
break;
default:
console.log("关闭:", event.code, event.reason);
}
};
保持连接活跃。
class WebSocketClient {
constructor(url) {
this.url = url;
this.ws = null;
this.heartbeatInterval = null;
this.heartbeatTimeout = null;
this.reconnectAttempts = 0;
this.maxReconnectAttempts = 5;
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => {
console.log("连接成功");
this.reconnectAttempts = 0;
this.startHeartbeat();
};
this.ws.onclose = () => {
console.log("连接关闭");
this.stopHeartbeat();
this.reconnect();
};
this.ws.onerror = (error) => {
console.error("连接错误:", error);
};
this.ws.onmessage = (event) => {
this.handleMessage(event.data);
};
}
startHeartbeat() {
this.heartbeatInterval = setInterval(() => {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify({ type: "ping" }));
this.heartbeatTimeout = setTimeout(() => {
console.log("心跳超时,关闭连接");
this.ws.close();
}, 5000);
}
}, 30000);
}
stopHeartbeat() {
clearInterval(this.heartbeatInterval);
clearTimeout(this.heartbeatTimeout);
}
handleMessage(data) {
const message = JSON.parse(data);
if (message.type === "pong") {
clearTimeout(this.heartbeatTimeout);
return;
}
console.log("收到消息:", message);
}
reconnect() {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);
console.log(`${delay}ms后重连...`);
setTimeout(() => {
this.connect();
}, delay);
}
}
send(data) {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(data));
}
}
close() {
this.stopHeartbeat();
this.ws.close(1000, "主动关闭");
}
}
// 使用
const client = new WebSocketClient("wss://api.db-w.cn/ws");
client.connect();
Socket.IO是WebSocket的增强库。
// 引入Socket.IO客户端
// <script src="/socket.io/socket.io.js"></script>
// 创建连接
const socket = io("https://api.db-w.cn");
// 连接事件
socket.on("connect", function() {
console.log("连接成功");
});
socket.on("disconnect", function() {
console.log("断开连接");
});
// 自定义事件
socket.on("message", function(data) {
console.log("收到消息:", data);
});
socket.on("notification", function(data) {
console.log("收到通知:", data);
});
// 发送消息
socket.emit("message", {
content: "东巴文"
});
// 发送并等待确认
socket.emit("request", { id: 1 }, function(response) {
console.log("服务器响应:", response);
});
// 加入房间
socket.emit("join", "room1");
// 离开房间
socket.emit("leave", "room1");
// 连接不同命名空间
const chatSocket = io("/chat");
const newsSocket = io("/news");
chatSocket.on("message", function(data) {
console.log("聊天消息:", data);
});
newsSocket.on("update", function(data) {
console.log("新闻更新:", data);
});
// 服务端广播到房间
socket.emit("broadcast", {
room: "lobby",
message: "欢迎加入"
});
// 广播给所有人(除了自己)
socket.broadcast.emit("announcement", "新用户加入");
// 广播到房间(除了自己)
socket.to("room1").emit("message", "房间消息");
class ChatClient {
constructor(url) {
this.ws = new WebSocket(url);
this.messages = [];
this.ws.onmessage = (event) => {
const message = JSON.parse(event.data);
this.handleMessage(message);
};
}
handleMessage(message) {
switch (message.type) {
case "message":
this.messages.push(message.data);
this.renderMessages();
break;
case "user_join":
console.log(`${message.data.name} 加入了聊天`);
break;
case "user_leave":
console.log(`${message.data.name} 离开了聊天`);
break;
}
}
send(content) {
this.ws.send(JSON.stringify({
type: "message",
content: content
}));
}
renderMessages() {
const container = document.getElementById("messages");
container.innerHTML = this.messages
.map(m => `<div>${m.user}: ${m.content}</div>`)
.join("");
}
}
// 使用
const chat = new ChatClient("wss://api.db-w.cn/chat");
chat.send("大家好!");
class RealtimeData {
constructor(url) {
this.ws = new WebSocket(url);
this.subscribers = new Map();
this.ws.onmessage = (event) => {
const data = JSON.parse(event.data);
this.notify(data.channel, data.payload);
};
}
subscribe(channel, callback) {
if (!this.subscribers.has(channel)) {
this.subscribers.set(channel, new Set());
this.ws.send(JSON.stringify({
type: "subscribe",
channel: channel
}));
}
this.subscribers.get(channel).add(callback);
return () => {
this.subscribers.get(channel).delete(callback);
};
}
notify(channel, data) {
const callbacks = this.subscribers.get(channel);
if (callbacks) {
callbacks.forEach(cb => cb(data));
}
}
}
// 使用
const realtime = new RealtimeData("wss://api.db-w.cn/realtime");
realtime.subscribe("stock:AAPL", (data) => {
console.log("苹果股价:", data.price);
updatePriceDisplay(data.price);
});
realtime.subscribe("news", (article) => {
console.log("新闻:", article.title);
});
掌握了WebSocket后,让我们继续学习:
东巴文(db-w.cn) - 让编程学习更简单
🎯 东巴文寄语:WebSocket是实现实时通信的核心技术,掌握心跳机制、重连策略和消息处理是构建实时应用的基础。在 db-w.cn,我们帮你掌握实时通信技术!