• 基于增强QUIC协议优化弱网下的直播观看体验


    如今,直播已成为电商、教育、娱乐等各领域信息传递与线上消费的重要载体,而网络质量则是决定直播体验的核心命脉。然而,当用户一旦置身于地铁、户外等弱网环境中,画面卡顿、画质模糊、音画错位等问题便接踵而至,原本精彩的直播瞬间变得支离破碎,用户观看体验随之直线下降。

    基于此,HarmonyOS SDK远场通信服务(Remote Communication Kit)提供了QUIC长连接能力,能够在即时通讯、实时推送、在线直播等场景中,显著提升通信效率,即使在弱网环境下,也能保障直播画面无卡顿、无时延,有效提高用户使用体验。

    1.png

    实现原理

    当应用冷启动时,传统网络请求需要经历域名解析、TCP连接建立、TLS握手等连接过程,在一次完整的请求中,连接阶段的操作会消耗大量时间,从而影响用户首屏加载体验。而QUIC长连接基于QUIC(Quick UDP Internet Connections)协议实现,相比传统的TCP协议,QUIC在速度、灵活性和稳定性方面更具备核心优势。

    我们以应用接收长连接服务端消息推送场景为例来进行说明。在服务端主动推送消息的场景下,QUIC长连接通过无队头阻塞的多路复用及更少的握手次数,有效优化传统HTTP/1.1及HTTP/2协议中的队头阻塞与多次握手问题,降低网络延迟和资源消耗。此外,QUIC长连接能够保持连接的持久性,减少连接建立和断开频率,进一步提升通信效率。

    2.png

    能力优势

    ● 抗弱网算法

    采用智能丢包重传与动态抖动缓冲技术,显著提升抗网络丢包和抖动能力,在30%丢包率下仍保障音视频清晰流畅。

    ● 物理链路无感切换

    支持Wi-Fi与蜂窝网络间无缝迁移,连接自动保持无需重建,用户无感知,通话或直播不中断,体验稳定可靠。

    ● 多路复用

    单连接内并行传输多路数据流,彻底消除队头阻塞,降低传输延迟,提升带宽利用率与并发性能,尤其适配实时通信场景。

    接收长连接服务端消息推送的开发实现步骤

    1. 在.cpp文件导入模块。
    #include "RemoteCommunicationKit/rcp_quic.h"
    #include 
    #include 
    #include 
    
    1. 在CMakeLists.txt文件中添加以下lib依赖包。
    librcp_quic.so
    
    1. 自定义全局变量,可用于QUIC连接与流配置。
    uint64_t g_StreamId = 0;
    uint64_t userData = 0;
    char *alpn = "h3";
    const char *serverName = "www.example.com"; // 示例代码,仅用于展示调用,实际运行请替换为真实的QUIC协议服务端地址
    uint64_t serverPort = 443; // 示例代码,仅用于展示调用,实际运行请替换为真实端口
    
    1. 自定义回调方法,用于后续步骤注册监听事件,可在回调中补充需要的业务逻辑。
    // 连接成功时触发
    void OnConnectedImpl(Rcp_QuicConn *conn, void *userObject) {
        (void)conn;
        if (userObject == NULL) {
            return;
        }
    }
    
    // 异常发生时触发
    void OnErrorImpl(Rcp_QuicConn *conn, void *userObject, Rcp_QuicErrorCode errCode, const char *errDetail) {
        (void)conn;
        if (errCode == 0 || userObject == NULL || errDetail == NULL) {
            return;
        }
    }
    
    // 连接关闭时触发
    void OnClosedImpl(Rcp_QuicConn *conn, void *userObject) {
        (void)conn;
        if (userObject == NULL) {
            return;
        }
    }
    
    // 接收到对端传输数据时触发,需要返回接收到的数据大小
    void OnReceiveDataImpl(Rcp_QuicConn *conn, void *userObject, uint64_t streamId,
                           const Rcp_QuicStreamData *streamData) {
        (void)conn;
        (void)streamId;
        (void)userObject;
        uint64_t totalBytes = 0;
        for (uint32_t i = 0; i < streamData->iovLen; i++) {
            totalBytes += streamData->iov[i].length;
        }
        return totalBytes;
    }
    
    // 接收到流事件时触发
    void onQuicStreamEventImpl(Rcp_QuicConn *conn, void *userObject, uint64_t streamId, Rcp_QuicErrorCode errCode,
                               const char *errDetail) {
        (void)conn;
        (void)userObject;
        (void)streamId;
        (void)errCode;
        (void)errDetail;
    }
    
    // 接收到对端创建流时触发
    void OnStreamInboundImpl(Rcp_QuicConn *conn, void *userObject, uint64_t streamId) {
        (void)conn;
        (void)userObject;
        g_StreamId = streamId;
    }
    
    1. 初始化QUIC配置项。
    // 创建QUIC会话对象,用于管理全局资源
    Rcp_QuicSession *session = HMS_Rcp_QuicCreateSession();
    // 创建QUIC连接对象,需要指定ALPN协议和用户对象
    Rcp_QuicConn *conn = HMS_Rcp_QuicConnCreate(alpn, &userData);
    // 设置连接建立成功时的回调
    HMS_Rcp_QuicConnSetOpt(conn, RCP_QUIC_CONN_ON_CONNECTED_FUNCTION, &OnConnectedImpl, 0);
    // 设置发生错误时的回调
    HMS_Rcp_QuicConnSetOpt(conn, RCP_QUIC_CONN_ON_ERROR_FUNCTION, &OnErrorImpl, 0);
    // 设置连接关闭时的回调
    HMS_Rcp_QuicConnSetOpt(conn, RCP_QUIC_CONN_ON_CLOSED_FUNCTION, &OnClosedImpl, 0);
    // 设置服务端创建流时的回调
    HMS_Rcp_QuicConnSetOpt(conn, RCP_QUIC_CONN_STREAM_INBOUND_FUNCTION, &OnStreamInboundImpl, 0);
    
    1. 与服务端进行连接。
    HMS_Rcp_QuicConnConnect(session, conn, serverName, serverPort);
    
    1. 服务端主动创建流,客户端接收到OnStreamInboundImpl回调后,为返回的对端流streamId设置监听事件。
    HMS_Rcp_QuicStreamSetOpt(conn, g_StreamId, RCP_QUIC_STREAM_EVENT_FUNCTION, &onQuicStreamEventImpl, 0);
    HMS_Rcp_QuicStreamSetOpt(conn, g_StreamId, RCP_QUIC_STREAM_DATA_FUNCTION, &OnReceiveDataImpl, 0);
    
    1. 业务完成后,关闭连接并释放资源。
    // 关闭流
    uint64_t appErr = 0; // 自定义业务状态码,服务端在流关闭时可以接收到此状态码用于对关闭原因进行判断
    HMS_Rcp_QuicConnStreamShutdown(conn, g_StreamId, RCP_QUIC_STREAM_SHUTDOWN_WRITE, appErr);
    HMS_Rcp_QuicConnStreamShutdown(conn, g_StreamId, RCP_QUIC_STREAM_SHUTDOWN_READ, appErr);
    
    // 销毁连接对象,关闭所有流并释放连接资源
    if (conn != NULL) {
        HMS_Rcp_QuicConnDestroy(conn);
    }
    
    // 销毁会话对象,释放QUIC全局资源
    if (session != NULL) {
        HMS_Rcp_QuicDestroySession(session);
    }
    

    了解更多详情>>

    访问远场通信服务联盟官网

    获取使用QUIC协议进行网络通信开发指导文档

  • 相关阅读:
    MyBatis-Plus 和swagger
    STM32HAL库使用ESP8266模块
    Hive数据仓库工具基本架构和入门部署详解
    Qt开发_调用OpenCV(4.x)完成人脸检测并绘制马赛克(摄像头实时数据)
    OSS业务存储适配器模式
    AI创作音乐引发的深思
    7.联合索引(最左前缀原则)
    修复MybatisX1.4.17版本插件误报@Mapkey is required错误
    Java学习笔记(三)——运算符
    【供应链】全面分析供应链类型
  • 原文地址:https://www.cnblogs.com/HarmonyOSSDK/p/22905803