QUIC长连接接收消息推送
=============

从26.0.0版本开始，新增支持QUIC长连接能力。

QUIC长连接基于QUIC（Quick UDP Internet Connections）协议实现，相比传统的TCP协议，QUIC在速度、灵活性和稳定性方面更具备核心优势。QUIC长连接在即时通讯、实时推送、在线协作等场景中具有广泛应用，能够显著提升通信效率和用户体验。在远场通信服务的框架中，QUIC长连接通过[RCP\_QUIC](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/rcp_quic_h)提供支持，为开发者提供高效、可靠的端云通信能力。

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

#### 接收长连接服务端消息推送

1.  在.cpp文件导入模块。
    
    #include "RemoteCommunicationKit/rcp\_quic.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
2.  在CMakeLists.txt文件中添加以下lib依赖包（具体请见[C API开发准备](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/remote-communication-preparations#c-api开发准备)）。
    
    librcp\_quic.so
    
3.  自定义全局变量，可用于QUIC连接与流配置。
    
    uint64\_t g\_StreamId = 0;
    uint64\_t userData = 0;
    char \*alpn = "h3";
    const char \*serverName = "www.example.com"; // 示例代码，仅用于展示调用，实际运行请替换为真实的QUIC协议服务端地址
    uint64\_t serverPort = 443; // 示例代码，仅用于展示调用，实际运行请替换为真实端口
    
4.  自定义回调方法，用于后续步骤注册监听事件，可在回调中补充需要的业务逻辑。
    
    // 连接成功时触发
    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;
    }
    
5.  初始化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);
    
6.  与服务端进行连接。
    
    HMS\_Rcp\_QuicConnConnect(session, conn, serverName, serverPort);
    
7.  服务端主动创建流，客户端接收到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);
    
8.  业务完成后，关闭连接并释放资源。
    
    // 关闭流
    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);
    }