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防止崩溃

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

相关推荐
Robot2512 小时前
「华为」人形机器人赛道投资首秀!
大数据·人工智能·科技·microsoft·华为·机器人
鸿蒙布道师2 小时前
鸿蒙NEXT开发动画案例5
android·ios·华为·harmonyos·鸿蒙系统·arkui·huawei
小诸葛的博客10 小时前
华为ensp实现跨vlan通信
网络·华为·智能路由器
康康这名还挺多12 小时前
鸿蒙HarmonyOS list优化一: list 结合 lazyforeach用法
数据结构·list·harmonyos·lazyforeach
晚秋大魔王15 小时前
OpenHarmony 开源鸿蒙南向开发——linux下使用make交叉编译第三方库——nettle库
linux·开源·harmonyos
python算法(魔法师版)19 小时前
.NET 在鸿蒙系统上的适配现状
华为od·华为·华为云·.net·wpf·harmonyos
bestadc20 小时前
鸿蒙 UIAbility组件与UI的数据同步和窗口关闭
harmonyos
枫叶丹421 小时前
【HarmonyOS Next之旅】DevEco Studio使用指南(二十二)
华为·harmonyos·deveco studio·harmonyos next
ax一号街阿楠1 天前
华为FAT AP配置 真机
网络·华为·智能路由器
吗喽对你问好1 天前
华为5.7机考第一题充电桩问题Java代码实现
java·华为·排序