WebSocket作为现代Web和应用开发中重要的实时通信协议,在鸿蒙NEXT中得到了很好的支持。本文将详细介绍如何在鸿蒙NEXT应用中使用WebSocket建立双向通信连接。
一、WebSocket简介与优势
WebSocket提供了全双工、双向的通信通道,相比传统的HTTP轮询具有以下优势:
-
实时性:服务器可以主动向客户端推送数据
-
低延迟:建立连接后无需重复握手
-
高效性:减少了不必要的HTTP头信息传输
-
持久连接:一次连接,多次通信
二、环境准备与权限配置
1. 导入NetworkKit
在oh-package.json5
中添加依赖:
json5
复制
下载
"dependencies": {
"@kit.NetworkKit": "^1.0.0"
}
执行 ohpm install
安装依赖。
2. 配置网络权限
在module.json5
中申请权限:
json5
复制
下载
"module": {
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
}
三、WebSocket基本使用
1. 创建WebSocket连接
typescript
复制
下载
import { webSocket } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
class WebSocketManager {
private ws: webSocket.WebSocket | null = null;
private url: string = 'wss://echo.websocket.org'; // WebSocket测试服务器
// 创建WebSocket连接
async connect(): Promise<void> {
try {
// 创建WebSocket实例
this.ws = await webSocket.createWebSocket(this.url);
// 设置连接回调
this.setupCallbacks();
// 建立连接
await this.ws.connect();
console.info('WebSocket连接建立成功');
} catch (error) {
const err: BusinessError = error as BusinessError;
console.error(`连接失败: Code: ${err.code}, Message: ${err.message}`);
}
}
// 设置各种回调函数
private setupCallbacks(): void {
if (!this.ws) return;
// 连接打开回调
this.ws.on('open', (err: BusinessError) => {
if (err) {
console.error(`连接打开错误: Code: ${err.code}, Message: ${err.message}`);
return;
}
console.info('WebSocket连接已打开');
// 连接建立后发送一条测试消息
this.sendMessage('Hello, HarmonyOS!');
});
// 接收到消息回调
this.ws.on('message', (err: BusinessError, data: string | ArrayBuffer) => {
if (err) {
console.error(`接收消息错误: Code: ${err.code}, Message: ${err.message}`);
return;
}
if (typeof data === 'string') {
console.info(`收到文本消息: ${data}`);
// 在这里处理接收到的文本消息,更新UI等
this.handleReceivedMessage(data);
} else {
console.info('收到二进制数据');
// 处理二进制数据
this.handleBinaryData(data);
}
});
// 连接关闭回调
this.ws.on('close', (err: BusinessError, code: number, reason: string) => {
if (err) {
console.error(`连接关闭错误: Code: ${err.code}, Message: ${err.message}`);
return;
}
console.info(`连接已关闭, Code: ${code}, Reason: ${reason}`);
// 可以在这里进行重连逻辑
});
// 错误回调
this.ws.on('error', (err: BusinessError) => {
console.error(`WebSocket错误: Code: ${err.code}, Message: ${err.message}`);
});
}
}
2. 发送消息
typescript
复制
下载
class WebSocketManager {
// ... 之前的代码 ...
// 发送文本消息
sendMessage(message: string): void {
if (!this.ws) {
console.error('WebSocket未连接');
return;
}
this.ws.send(message, (err: BusinessError) => {
if (err) {
console.error(`发送消息失败: Code: ${err.code}, Message: ${err.message}`);
return;
}
console.info('消息发送成功');
});
}
// 发送二进制数据
sendBinaryData(data: ArrayBuffer): void {
if (!this.ws) {
console.error('WebSocket未连接');
return;
}
this.ws.send(data, (err: BusinessError) => {
if (err) {
console.error(`发送二进制数据失败: Code: ${err.code}, Message: ${err.message}`);
return;
}
console.info('二进制数据发送成功');
});
}
}
3. 关闭连接
typescript
复制
下载
class WebSocketManager {
// ... 之前的代码 ...
// 关闭WebSocket连接
closeConnection(): void {
if (!this.ws) {
console.info('WebSocket未连接,无需关闭');
return;
}
this.ws.close((err: BusinessError) => {
if (err) {
console.error(`关闭连接失败: Code: ${err.code}, Message: ${err.message}`);
return;
}
console.info('WebSocket连接已关闭');
this.ws = null;
});
}
// 带状态码的关闭
closeWithCode(code: number, reason: string): void {
if (!this.ws) {
return;
}
this.ws.close({ code, reason }, (err: BusinessError) => {
if (err) {
console.error(`关闭连接失败: Code: ${err.code}, Message: ${err.message}`);
return;
}
console.info(`WebSocket连接已关闭,Code: ${code}, Reason: ${reason}`);
this.ws = null;
});
}
}
四、完整的使用示例
下面是一个完整的聊天室示例:
typescript
复制
下载
import { webSocket } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
interface ChatMessage {
type: 'user_join' | 'user_leave' | 'message';
user: string;
content: string;
timestamp: number;
}
class ChatRoom {
private ws: webSocket.WebSocket | null = null;
private url: string = 'wss://your-chat-server.com/ws';
private userName: string = '';
constructor(userName: string) {
this.userName = userName;
}
// 加入聊天室
async joinChatRoom(): Promise<void> {
try {
this.ws = await webSocket.createWebSocket(this.url);
this.setupCallbacks();
await this.ws.connect();
} catch (error) {
const err: BusinessError = error as BusinessError;
console.error(`加入聊天室失败: ${err.message}`);
throw err;
}
}
private setupCallbacks(): void {
if (!this.ws) return;
this.ws.on('open', () => {
console.info('已加入聊天室');
// 发送加入通知
this.sendChatMessage('', 'user_join');
});
this.ws.on('message', (err: BusinessError, data: string | ArrayBuffer) => {
if (err) return;
if (typeof data === 'string') {
this.handleChatMessage(data);
}
});
this.ws.on('close', () => {
console.info('已离开聊天室');
});
}
// 处理接收到的聊天消息
private handleChatMessage(data: string): void {
try {
const message: ChatMessage = JSON.parse(data);
switch (message.type) {
case 'user_join':
console.info(`用户 ${message.user} 加入了聊天室`);
break;
case 'user_leave':
console.info(`用户 ${message.user} 离开了聊天室`);
break;
case 'message':
console.info(`${message.user}: ${message.content}`);
// 更新UI显示消息
this.displayMessage(message);
break;
}
} catch (error) {
console.error('解析消息失败');
}
}
// 发送聊天消息
sendTextMessage(content: string): void {
this.sendChatMessage(content, 'message');
}
private sendChatMessage(content: string, type: 'user_join' | 'user_leave' | 'message'): void {
if (!this.ws) return;
const message: ChatMessage = {
type,
user: this.userName,
content,
timestamp: Date.now()
};
this.ws.send(JSON.stringify(message), (err: BusinessError) => {
if (err) {
console.error('发送消息失败');
}
});
}
// 离开聊天室
leaveChatRoom(): void {
if (!this.ws) return;
// 发送离开通知
this.sendChatMessage('', 'user_leave');
setTimeout(() => {
this.closeWithCode(1000, '用户主动离开');
}, 100);
}
private closeWithCode(code: number, reason: string): void {
if (!this.ws) return;
this.ws.close({ code, reason }, (err: BusinessError) => {
if (!err) {
this.ws = null;
}
});
}
private displayMessage(message: ChatMessage): void {
// 在这里实现UI更新逻辑
// 例如:将消息添加到聊天界面
console.info(`[UI更新] ${message.user}: ${message.content}`);
}
}
// 使用示例
// const chatRoom = new ChatRoom('张三');
// await chatRoom.joinChatRoom();
// chatRoom.sendTextMessage('大家好!');
五、高级功能与最佳实践
1. 自动重连机制
typescript
复制
下载
class RobustWebSocket extends WebSocketManager {
private reconnectAttempts: number = 0;
private maxReconnectAttempts: number = 5;
private reconnectInterval: number = 3000; // 3秒
private setupCallbacks(): void {
if (!this.ws) return;
this.ws.on('close', (err: BusinessError, code: number, reason: string) => {
if (err) {
console.error(`连接关闭错误: ${err.message}`);
}
// 非正常关闭时尝试重连
if (code !== 1000) {
this.attemptReconnect();
}
});
}
private attemptReconnect(): void {
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
console.error('达到最大重连次数,停止重连');
return;
}
this.reconnectAttempts++;
console.info(`第${this.reconnectAttempts}次尝试重连...`);
setTimeout(async () => {
try {
await this.connect();
this.reconnectAttempts = 0; // 重置重连计数
console.info('重连成功');
} catch (error) {
console.error('重连失败,继续尝试...');
this.attemptReconnect();
}
}, this.reconnectInterval);
}
}
2. 心跳检测
typescript
复制
下载
class HeartbeatWebSocket extends WebSocketManager {
private heartbeatInterval: number = 30000; // 30秒
private heartbeatTimer: number | undefined;
protected setupCallbacks(): void {
super.setupCallbacks();
if (!this.ws) return;
this.ws.on('open', () => {
this.startHeartbeat();
});
this.ws.on('close', () => {
this.stopHeartbeat();
});
}
private startHeartbeat(): void {
this.stopHeartbeat();
this.heartbeatTimer = setInterval(() => {
if (this.ws) {
this.sendMessage('ping');
}
}, this.heartbeatInterval) as unknown as number;
}
private stopHeartbeat(): void {
if (this.heartbeatTimer) {
clearInterval(this.heartbeatTimer);
this.heartbeatTimer = undefined;
}
}
}
六、注意事项
-
权限管理:确保在配置文件中正确声明网络权限
-
资源释放:在页面销毁时记得关闭WebSocket连接
-
错误处理:妥善处理各种网络异常情况
-
性能优化:避免频繁创建和销毁连接
-
安全性:使用WSS(WebSocket Secure)协议传输敏感数据
七、总结
鸿蒙NEXT的WebSocket API提供了强大而灵活的实时通信能力。通过本文的介绍,你应该已经掌握了:
-
WebSocket连接的基本创建和管理
-
消息的发送和接收处理
-
各种回调函数的正确使用
-
高级功能如自动重连和心跳检测
-
在实际项目中的最佳实践
WebSocket为鸿蒙应用开启了实时通信的大门,无论是聊天应用、实时游戏、在线协作还是实时数据监控,都能找到它的用武之地。