在鸿蒙NEXT中使用WebSocket实现实时网络通信

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;
    }
  }
}

六、注意事项

  1. 权限管理:确保在配置文件中正确声明网络权限

  2. 资源释放:在页面销毁时记得关闭WebSocket连接

  3. 错误处理:妥善处理各种网络异常情况

  4. 性能优化:避免频繁创建和销毁连接

  5. 安全性:使用WSS(WebSocket Secure)协议传输敏感数据

七、总结

鸿蒙NEXT的WebSocket API提供了强大而灵活的实时通信能力。通过本文的介绍,你应该已经掌握了:

  • WebSocket连接的基本创建和管理

  • 消息的发送和接收处理

  • 各种回调函数的正确使用

  • 高级功能如自动重连和心跳检测

  • 在实际项目中的最佳实践

WebSocket为鸿蒙应用开启了实时通信的大门,无论是聊天应用、实时游戏、在线协作还是实时数据监控,都能找到它的用武之地。

相关推荐
不会吃萝卜的兔子16 小时前
springboot websocket 原理
spring boot·后端·websocket
野木香18 小时前
go语言websocket连接,重连,发心跳示例
websocket·go
从零开始学习人工智能1 天前
分布式 WebSocket 架构设计与实现:跨节点实时通信解决方案
分布式·websocket·网络协议
fruge1 天前
提升 HarmonyOS 开发效率:DevEco Studio 6.0 热更新调试模式全指南
华为·harmonyos
2501_919749031 天前
鸿蒙:使用Image组件展示相册图片或rawfile图片
华为·harmonyos
2501_919749031 天前
鸿蒙:PersistenceV2页面间持久化存储数据
华为·harmonyos
vortex51 天前
WebSocat 安装与使用
websocket
yenggd1 天前
QoS之拥塞管理两种配置方法
网络·华为
一尘之中1 天前
操作系统内核架构深度解析:从单内核、微内核到鸿蒙分布式设计
架构·harmonyos·ai写作