HarmonyOS 鸿蒙Next网络协议WebSocket

HarmonyOS 鸿蒙Next网络协议WebSocket

Websocket

  1. 消息推送常见方式:轮询,长轮询,SSE,Websocket

    • 轮询:指定间隔时间向服务器发送HTTP请求 缺点:存在延迟,服务器压力大

    • 长轮询:发出异步请求,服务器接到请求后,会阻塞请求,直到有数据或者超时才返回

    • SSE(server-sent-event):前端发出请求,服务器给前端打开单向通道,响应返回数据流,然后实时向前端传输数据,直到通道关闭

    • Websocket:是一种基于TCP连接上进行全双工通信的协议

http是规定了客户端(如浏览器)与服务器之间传输数据的格式和通信方式 websocket也是一种规定了客户端和服务器传输数据格式和通信方式的协议

  • 全双工: 允许数据在两个方向上同时传输
  • 半双工:允许数据在两个方向上传输,但是一个时间段内只允许一个方向上传输

当浏览器向服务器发送请求以切换到 WebSocket 连接时,这个过程通常称为 WebSocket 握手。这个握手过程是基于 HTTP 协议的,因为 WebSocket 需要使用 HTTP 请求来启动连接。

以下是 WebSocket 握手的基本步骤:

  1. 客户端发起请求:浏览器通过发送一个特殊的 HTTP 请求到服务器来开始 WebSocket 握手。这个请求包含了 Upgrade 头部,表明客户端希望将连接从 HTTP 升级到 WebSocket。例如:
GET /websocket HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
  1. 服务器响应:如果服务器同意升级连接,它会发送一个 HTTP 响应,状态码为 101(Switching Protocols),表明它同意进行协议升级。这个响应也包含了一些额外的头部,如 UpgradeConnection,以及 Sec-WebSocket-Accept,后者是服务器对客户端 Sec-WebSocket-Key 的回应。例如:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
  1. 连接建立:一旦客户端收到服务器的 101 响应,WebSocket 连接就正式建立。之后,所有的数据传输都将通过 WebSocket 协议进行,而不是 HTTP。

  2. 数据传输:在 WebSocket 连接建立后,服务器和客户端之间将使用 WebSocket 协议进行全双工通信。这意味着双方可以同时发送和接收数据,而不受 HTTP 请求-响应模型的限制。

总结来说,虽然 WebSocket 握手开始于一个 HTTP 请求,但一旦握手完成,所有的通信都将通过 WebSocket 协议进行,而不是 HTTP。这种设计允许 WebSocket 利用现有的 HTTP 端口(通常是 80 或 443)来建立连接,从而更容易地通过防火墙和代理服务器。

基本用法:

  1. 添加依赖:
implementation(libs.okhttp)
  1. 创建WebSocket监听器继承自WebSocketListener,重写四个方法
class EchoWebSocketListener:WebSocketListener() {
    override fun onOpen(webSocket: WebSocket, response: Response) {
       Log.d("WS","连接已建立")
        webSocket.send("Hello World")
    }

    override fun onMessage(webSocket: WebSocket, text: String) {
       Log.d("WS","收到消息:$text")
    }

    override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
        webSocket.close(1000,null)
        Log.d("WS"," 错误:$reason")
    }

    override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
       Log.d("WS","错误:${t.message}")
    }
}
  1. 创建WebSocket
class MainActivity : AppCompatActivity() {
    private lateinit var webSocket:WebSocket
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        val binding= ActivityMainBinding.inflate(layoutInflater)
             binding.btn.setOnClickListener {
            startWebSocket()
        }

    }

    private fun startWebSocket(){
        val client=OkHttpClient.Builder()
        .pingInterval(30, TimeUnit.SECONDS)//设置心跳间隔,并且用枚举类型指定单位为秒
        .build()
        val request=Request.Builder()
        .url("ws://echo.websocket.org").build()//传入服务器(自动返回发送的信息)的地址
        val listener=EchoWebSocketListener()
        webSocket=client.newWebSocket(request, listener)//发送握手请求,但是还未建立,完成握手后,会调用onOpen(),30秒后去发送第一个Ping
    }

心跳的作用:

    1. 定期发送PING帧,防止中间设备误杀连接
    1. 快速感知服务器或者是网络故障,如果 PING 未立即(毫秒级延迟)收到 PONG 响应,客户端能 秒级感知 并触发重连,而非一直等待。
    1. 通过PING维持连接活跃,避免服务器主动关闭空闲连接。

设置心跳间隔一般小于接收Pong超时时间:(如果接收Pong超时为20s,间隔为30s)

  • t=0s:建立了连接

  • t=30s:发送第一次ping,启动超时计时器

  • t=31s:接收到pong,超时计时器重置(到51s超时)也就是说如果31s到51s之间没有任何数据传输就会超时,而下一次发送ping是在t=60s,所有导致了超时

  • writeTimeout:用于设置写操作的超时时间,防止发送数据时长时间阻塞。(sent)

  • callTimeout:用于远程过程调用,设置等待服务器响应的最大时间。

  • readTimeout:用于设置从连接中读取数据的超时时间,确保在一定时间内接收到数据。

  • connectTimeout:用于设置建立连接的超时时间,确保在一定时间内连接成功。

代码实现:

package com.example.websocket

import android.nfc.Tag
import android.os.Handler
import android.os.Looper
import android.util.Log
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.WebSocket
import okhttp3.WebSocketListener
import java.util.concurrent.TimeUnit

class EchoWebSocketListener:WebSocketListener() {
    private var webSocket: WebSocket? = null
    private val handler=Handler(Looper.getMainLooper())
    private val reconnectInterval=5000L
    private val maxReconnectAttempts=5
    private var reconnectAttempts=0
    override fun onOpen(webSocket: WebSocket, response: Response) {
        this.webSocket=webSocket
       Log.d("WS","连接已建立")
        webSocket.send("Hello World")
    }

    override fun onMessage(webSocket: WebSocket, text: String) {
       Log.d("WS","收到消息:$text")
    }

    override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
        webSocket.close(code,reason)
        when(code){
            1000->Log.d("WS","正常关闭")
            else->{Log.d("Ws", reason)
            scheduleReconnect()
            }
        }
        Log.d("WS"," 错误:$reason")
    }

    override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
       Log.d("WS","错误:${t.message}")
        scheduleReconnect()
    }
    private fun scheduleReconnect(){
        if(reconnectAttempts>=maxReconnectAttempts){
            Log.d("Ws","重连次数以达到上限")
            return
        }
        handler.postDelayed({
           Log.d("WS","正在尝试重连...")
            webSocket?.cancel()// 取消旧连接
            val client= OkHttpClient.Builder()
                .pingInterval(30, TimeUnit.SECONDS)
                .build()
            val request=Request.Builder()
                .url("ws://echo.websocket.org")
                .build()
            val newWebSocket=client.newWebSocket(request,this)
            webSocket=newWebSocket//把新的webSocket赋给webSocket
        },reconnectInterval)
    }
}

private val handler=Handler(Looper.getMainLooper())

这行代码创建了一个 Handler 实例,并将其与主线程(UI 线程)关联起来。Looper.getMainLooper() 方法返回应用程序的主线程的 Looper 实例。通过传递这个 LooperHandler 构造函数,您确保了 Handler 将在主线程上执行其 Runnable 任务。

Handler 类用于在指定的线程上执行任务,通常是在主线程(UI 线程)上。Handler 提供了一种方式来处理线程间的通信,特别是当需要在主线程上执行任务时。

状态码

  • 1000:正常关闭(如页面导航离开)
  • 1001:服务端主动断开(如维护重启)
  • 1006:异常断开(常见于网络问题)
  • 1012:服务端不可用(如负载过高)

更多关于HarmonyOS 鸿蒙Next网络协议WebSocket的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

鸿蒙Next的WebSocket实现基于标准RFC 6455协议,提供全双工通信能力。开发者可使用@ohos.net.socket模块创建WebSocket连接,主要接口包括:

  1. createWebSocket()初始化连接对象
  2. connect()建立服务器连接
  3. send()发送文本/二进制数据
  4. 通过on('message')等事件监听器处理数据

典型代码结构:

import webSocket from '@ohos.net.socket';
let ws = webSocket.createWebSocket();
ws.on('open', () => {
  ws.send("Hello Server");
});
ws.connect('ws://example.com');

支持TLS加密连接,需配置extraOptions中的安全参数。连接状态通过readyState属性获取。

更多关于HarmonyOS 鸿蒙Next网络协议WebSocket的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中使用WebSocket需要注意以下几点:

  1. 连接建立流程与标准WebSocket一致,都是通过HTTP 101协议切换完成握手

  2. 推荐使用okhttp库实现WebSocket客户端,其API与Android保持兼容

  3. 心跳机制配置建议:

    • 设置pingInterval为30秒左右
    • 确保接收pong超时时间大于心跳间隔
    • 可通过OkHttpClient.Builder配置超时参数
  4. 连接状态管理要点:

    • 实现自动重连机制
    • 正确处理各种关闭状态码(1000/1001/1006等)
    • 使用Handler确保回调在主线程执行
  5. 性能优化建议:

    • 合理设置各超时参数
    • 实现消息队列避免频繁发送
    • 注意资源释放防止内存泄漏

WebSocket在HarmonyOS Next中的API使用与Android基本一致,开发者可以平滑迁移现有代码。

回到顶部