HarmonyOS WebSocket全场景应用开发深度解析

注:适用版本(Harmony OS NEXT / 5.0 / API 12+ )

一、最终效果预览

二、基础代码结构

javascript 复制代码
@Entry
@Component
struct ChatApp {
  @State messages: Message[] = []  // 所有聊天记录
  @State inputText: string = ""    // 输入框内容
  @State isConnected: boolean = false // 是否在线

  private ws: webSocket.WebSocket | null = null

  // 建立连接
  private connect() {
    this.ws = webSocket.createWebSocket()
    this.ws.connect('wss://toolin.cn/echo')
    
    // 四个关键监听
    this.ws.on('open', () => this.isConnected = true)
    this.ws.on('message', (data) => {
      this.messages = [...this.messages, new Message('received', data.message)]
    })
    this.ws.on('close', () => this.isConnected = false)
    this.ws.on('error', (err) => console.error('出错啦:', err))
  }

  // 发送消息
  private sendMessage() {
    if (this.inputText && this.isConnected) {
      this.ws?.send(this.inputText)
      this.messages = [...this.messages, new Message('sent', this.inputText)]
      this.inputText = ""
    }
  }

  build() { /* 界面代码 */ }
}

三、核心功能

1、连接状态管理
javascript 复制代码
// 显示连接状态
Text(this.isConnected ? '🟢 在线' : '🔴 离线')
  .fontColor(this.isConnected ? Color.Green : Color.Red)

// 连接/断开按钮
Button(this.isConnected ? '断开连接' : '点击连接')
  .onClick(() => {
    this.isConnected ? this.ws?.close() : this.connect()
  })
2、消息收发演示
javascript 复制代码
// 消息输入框
TextInput({ text: this.inputText, placeholder: '说点什么...'})
  .onChange((text) => this.inputText = text)

// 发送按钮
Button('发送')
  .onClick(() => this.sendMessage())

// 消息气泡样式
List() {
  ForEach(this.messages, (msg) => {
    ListItem() {
      Text(`${msg.type === 'sent' ? '我' : '对方'}: ${msg.content}`)
        .backgroundColor(msg.type === 'sent' ? '#e3f2fd' : '#ffffff')
        .padding(10)
        .borderRadius(8)
    }
  })
}

3、自动重连机制(心跳机制)

php 复制代码
// 简单重连逻辑
private reconnect() {
  setTimeout(() => {
    console.log('尝试重新连接...')
    this.connect()
  }, 3000) // 3秒后重试
}

// 在连接断开时触发
this.ws.on('close', () => {
  this.isConnected = false
  this.reconnect() // 自动重连
})

四**、源码详情**

javascript 复制代码
import webSocket from '@ohos.net.webSocket' // 导入 WebSocket 模块
import { promptAction } from '@kit.ArkUI' // 导入弹窗模块

export class Message { // 定义消息类
  type: 'sent' | 'received' // 消息类型,发送或接收
  content: string // 消息内容
  timestamp: number // 消息时间戳

  constructor(type: 'sent' | 'received', content: string) { // 构造函数
    this.type = type // 设置消息类型
    this.content = content // 设置消息内容
    this.timestamp = new Date().getTime() // 设置当前时间戳
  }
}

@Entry // 标记为入口组件
@Component // 标记为组件
struct WebSocketDemo { // 定义 WebSocketDemo 组件
  // WebSocket 连接状态
  @State isConnected: boolean = false // 初始化为未连接
  // 消息输入框内容
  @State inputMessage: string = '' // 初始化为空字符串
  // 消息记录列表
  @State messages: Message[] = [] // 初始化为空数组
  // WebSocket 对象
  private ws: webSocket.WebSocket | null = null // 初始化为 null


  // 初始化 WebSocket
  private initWebSocket() {
    const wsUrl = 'wss://toolin.cn/echo' // 使用公共测试服务器

    try {
      this.ws = webSocket.createWebSocket() // 创建 WebSocket 实例
      // 注册事件监听
      this.ws.on('open', () => { // 监听连接打开事件
        this.isConnected = true // 设置连接状态为已连接
        this.addMessage('received', '连接已建立') // 添加连接成功消息
      })

      this.ws.on('message', (data) => { // 监听消息事件
        // 检查 data 对象是否包含 message 属性
        if (data && data.message) {
          this.addMessage('received', `收到消息: ${data.message}`) // 添加收到的消息
        } else {
          console.error('Received unexpected data:', data) // 输出错误日志
        }
      })

      this.ws.on('close', () => { // 监听连接关闭事件
        this.isConnected = false // 设置连接状态为未连接
        this.addMessage('received', '连接已关闭') // 添加连接关闭消息
      })

      this.ws.on('error', (err: Error) => { // 监听错误事件
        console.error('WebSocket 错误:', err) // 输出错误日志
        this.showAlert(`错误: ${err.message}`) // 显示错误弹窗
      })

      // 发起连接
      this.ws.connect(wsUrl) // 连接到 WebSocket 服务器
    } catch (error) {
      this.showAlert(`初始化失败: ${error.message}`) // 显示初始化失败弹窗
    }
  }

  // 添加消息到列表
  private addMessage(type: 'sent' | 'received', content: string) {
    this.messages = [...this.messages, new Message(type, content)] // 将新消息添加到消息列表
  }

  // 显示弹窗
  private async showAlert(message: string) {
    const res = await promptAction.showDialog({ // 显示弹窗
      title: '提示', // 弹窗标题
      message: message, // 弹窗内容
      buttons: [ // 弹窗按钮
        { text: '取消', color: '#999999' }, // 取消按钮
        { text: '确定', color: '#007aff' } // 确定按钮
      ]
    })
  }

  build() {
    Column() { // 垂直布局
      // 连接状态显示
      Text(this.isConnected ? '已连接' : '未连接') // 显示连接状态
        .fontColor(this.isConnected ? Color.Green : Color.Red) // 设置字体颜色
        .margin(10) // 设置外边距

      // 控制按钮
      Row() { // 水平布局
        Button(this.isConnected ? '断开连接' : '建立连接') // 根据连接状态显示按钮文本
          .onClick(() => { // 点击事件处理
            if (this.isConnected) {
              this.ws?.close() // 关闭 WebSocket 连接
              this.ws = null // 将 WebSocket 对象设置为 null
            } else {
              this.initWebSocket() // 初始化 WebSocket 连接
            }
          })
          .margin(5) // 设置外边距

        Button('清空记录') // 清空记录按钮
          .onClick(() => this.messages = []) // 清空消息列表
          .margin(5) // 设置外边距
      }

      // 消息输入区
      TextInput({ text: this.inputMessage,placeholder:'请输入消息'}) // 文本输入框
        .onChange((value: string) => this.inputMessage = value) // 输入内容变化时更新 inputMessage
        .margin(10) // 设置外边距
        .height(60) // 设置高度
        .width('90%') // 设置宽度

      Button('发送消息') // 发送消息按钮
        .onClick(() => { // 点击事件处理
          if (this.inputMessage.trim() && this.isConnected) { // 检查输入内容和连接状态
            this.ws?.send(this.inputMessage) // 发送消息
            this.addMessage('sent', this.inputMessage) // 添加发送的消息
            this.inputMessage = '' // 清空输入框
          }
        })
        .margin(10) // 设置外边距

      // 消息记录列表
      List({ space: 10 }) { // 列表布局
        ForEach(this.messages, (msg: Message) => { // 遍历消息列表
          ListItem() { // 列表项
            Column() { // 垂直布局
              Text(`${msg.type === 'sent' ? '[发送]' : '[接收]'} ${msg.content}`) // 显示消息类型和内容
                .fontSize(14) // 设置字体大小
                .fontColor(msg.type === 'sent' ? Color.Blue : Color.Gray) // 设置字体颜色

              Text(new Date(msg.timestamp).toLocaleTimeString()) // 显示消息时间
                .fontSize(10) // 设置字体大小
                .fontColor(Color.Gray) // 设置字体颜色
            }
            .padding(10) // 设置内边距
            .width('100%') // 设置宽度
            .alignItems(msg.type === 'sent' ? HorizontalAlign.End : HorizontalAlign.Start) // 设置对齐方式
          }
        })
      }
      .layoutWeight(1) // 设置布局权重
      .divider({ strokeWidth: 1, color: '#eee' }) // 设置分隔线
    }
    .width('100%') // 设置宽度
    .height('100%') // 设置高度
    .padding(10) // 设置内边距
    .backgroundColor('#f0f0f0') // 设置背景颜色
  }
}

五、问题优化

1、权限配置问题

存在原因:

网络请求失败

控制台报错PERMISSION_DENIED

解决方法:module.josn5配置文件中配置网络权限

javascript 复制代码
// module.json5 配置  
"requestPermissions": [  
  {  
    "name": "ohos.permission.INTERNET",  
  }  
]  

2、 消息安全性风险

javascript 复制代码
// 消息内容过滤  
private sanitizeMessage(content: string): string {  
  return content  
    .replace(/</g, '&lt;')  
    .replace(/>/g, '&gt;')  
    .substring(0, 500); // 限制消息长度  
}  

3. 防止频繁发送

javascript 复制代码
private lastSendTime: number = 0

sendMessage() {
  if (Date.now() - this.lastSendTime < 1000) {
    promptAction.showToast({ message: '发送太频繁啦!' })
    return
  }
  // ...正常发送逻辑
  this.lastSendTime = Date.now()
}

五、总结

  1. 测试地址 :先用wss://echo.websocket.org这种公共测试服务

  2. 真机调试:记得在手机设置里打开应用的网络权限

  3. 基础样式:先实现功能再美化界面

  4. 错误处理:关键操作添加try-catch防止崩溃

通过这个简化版,开发者可以快速搭建基础聊天功能,再逐步添加进阶特性。建议先跑通基础代码,再按需扩展功能!

相关推荐
小2不语4 小时前
Huawei H151-370 5G CPE 5 SE Review
5g·华为
秋叶先生_4 小时前
HarmonyOS NEXT——【鸿蒙监听网络状态变化】
华为·harmonyos·鸿蒙
东林知识库4 小时前
鸿蒙NEXT小游戏开发:围住神经猫
harmonyos
zacksleo4 小时前
鸿蒙Flutter开发故事:不,你不需要鸿蒙化
flutter·harmonyos
chat2tomorrow5 小时前
数据仓库是什么?数据仓库的前世今生 (数据仓库系列一)
大数据·数据库·数据仓库·低代码·华为·spark·sql2api
别说我什么都不会6 小时前
OpenHarmony解读之设备认证:sts协议-客户端发起sts end请求
物联网·嵌入式·harmonyos
悬空八只脚9 小时前
React-Native开发鸿蒙NEXT-本地与沙盒加载bundle
harmonyos
鸿蒙布道师10 小时前
鸿蒙NEXT开发日志工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
90后的晨仔10 小时前
HarmonyOS的页面生命周期 和 组件生命周期
harmonyos
桃子酱紫君20 小时前
华为配置篇-ISIS基础实验
华为