# HarmonyOS 远场通信服务:在你的APP里用 C++ 发起 HTTP 请求
什么是远场通信服务
你写过网络请求代码吗?比如用 HTTP 从服务器获取数据。在鸿蒙开发中,用 ArkTS 发 HTTP 请求是很常见的。但有些场景需要更高的性能,比如游戏、音视频处理,这时候用 C++ 来发请求会更快。
远场通信服务(Remote Communication Kit)就是 HarmonyOS 提供的网络请求工具。它提供了 C 语言的 API,让你可以在 C++ 中发起 HTTP 请求。
你可能会问:ArkTS 不是有网络请求的接口吗?为什么还要用 C++?原因有几点:
- 性能:C++ 的执行速度比 ArkTS 快很多,特别是在处理大量数据时
- 复用:如果你已经有现成的 C++ 网络库,可以直接用,不用重写
- 底层控制:C++ 可以更精细地控制网络行为,比如超时、重试、断点续传等
简单说,远场通信服务就是让你用 C++ 来发 HTTP 请求,适合对性能要求高的场景。
核心功能
远场通信服务提供以下功能:
- 基础 URL 请求:发送 HTTP GET/POST 请求。这是最基本的功能,从服务器获取数据
- 超时控制:设置连接超时和传输超时。防止网络请求卡住,等太久用户体验差
- 断点续传:支持大文件断点续传。下载大文件时,如果网络断了,可以从断点继续下载,不用重新开始
环境搭建
硬件要求
- 设备类型:华为手机
- HarmonyOS 系统:HarmonyOS 5.0.0 Release 及以上
软件要求
- DevEco Studio 版本:DevEco Studio 6.0.0 Release 及以上
- HarmonyOS SDK 版本:HarmonyOS 6.0.0 Release SDK 及以上
搭建步骤
- 安装 DevEco Studio:去华为开发者官网下载安装
- 配置开发环境:确保网络环境正常
- 设备调试:使用真机进行调试
项目结构
├── entry/src/main │ ├── cpp │ │ ├── CMakeLists.txt // C 文件编译脚本 │ │ ├── napi_init.cpp // C 接口封装为 ArkTS │ │ └── types │ │ └── libentry │ │ ├── Index.d.ts // 导出封装的 ArkTS 接口 │ │ └── oh-package.json5 // ArkTS 与动态库映射 │ └── ets │ ├── entryability │ │ └── MainAbility.ets // UI Ability │ └── pages │ ├── BaseAddress.ets // 基础 URL 测试页面 │ ├── MainPage.ets // 主界面 │ ├── TimeOut.ets // 超时测试页面 │ └── TransferRange.ets // 断点续传页面这个项目是 C++ 和 ArkTS 混合开发的:
cpp目录:C++ 代码,包括编译脚本、NAPI 封装ets目录:ArkTS 代码,包括页面和业务逻辑
你可能会问:什么是 NAPI?NAPI 是 Node-API 的缩写,是鸿蒙系统提供的 C++ 和 ArkTS 之间的桥梁。通过 NAPI,ArkTS 可以调用 C++ 的函数。
C++ HTTP 请求流程
下面是使用 C++ 发起 HTTP 请求的完整流程:
NAPI 封装流程
下面是 C++ 接口封装为 ArkTS 接口的流程:
第一步:配置编译脚本
在CMakeLists.txt中配置远场通信 SDK:
# the minimum version of CMake. cmake_minimum_required(VERSION 3.4.1) project(RemoteCommunicationKitSdk) set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) if(DEFINED PACKAGE_FIND_FILE) include(${PACKAGE_FIND_FILE}) endif() include_directories(${NATIVERENDER_ROOT_PATH} ${NATIVERENDER_ROOT_PATH}/include) include_directories(${HMOS_SDK_NATIVE}/sysroot/usr/include) link_directories(${HMOS_SDK_NATIVE}/sysroot/usr/lib/aarch64-linux-ohos) add_library(entry SHARED napi_init.cpp) target_link_libraries(entry PUBLIC libace_napi.z.so librcp_c.so libhilog_ndk.z.so)这里配置了:
- 头文件路径:远场通信 SDK 的头文件。C++ 编译时需要知道去哪里找这些头文件
- 链接库:
librcp_c.so是远场通信的核心库。你的 C++ 代码最终会链接到这个库 - 编译目标:
entry是编译出来的动态库名字。ArkTS 通过这个名字来调用 C++ 代码
你可能会觉得这些配置很复杂。其实你不需要完全理解每一行,只要知道"这是告诉编译器去哪里找远场通信的库"就行了。
第二步:配置网络权限
在module.json5中添加网络权限:
{"requestPermissions":[{"name":"ohos.permission.INTERNET"}]}没有这个权限,网络请求会失败。这是鸿蒙系统的安全机制,应用必须声明需要网络权限,才能访问网络。
第三步:配置页面跳转
在main_pages.json中配置页面路径:
{"src":["pages/MainPage","pages/BaseAddress","pages/TimeOut","pages/TransferRange"]}配置好页面路径后,才能在不同页面之间跳转。这个文件告诉系统"我的应用有哪些页面"。
第四步:在 C++ 中发起 HTTP 请求
这是核心部分。在 C++ 中使用远场通信 SDK 发起请求。
引用头文件
#include"RemoteCommunicationKit/rcp.h"引入远场通信 SDK 的头文件。rcp.h包含了所有的 API 函数声明。
配置请求参数
Rcp_Request*request=nullptr;Rcp_Configuration cfg{};cfg.transferConfiguration.timeout.connectMs=3000;// 连接超时 3 秒cfg.transferConfiguration.timeout.transferMs=10000;// 传输超时 10 秒if((request=HMS_Rcp_CreateRequest(url))==nullptr){gotoExit;}request->configuration=&cfg;创建请求对象,配置超时时间:
connectMs:连接超时时间(毫秒)。3000 毫秒 = 3 秒,意思是如果 3 秒内连不上服务器,就放弃transferMs:传输超时时间(毫秒)。10000 毫秒 = 10 秒,意思是如果 10 秒内数据没传输完,就放弃
为什么要设置超时?因为网络请求可能会卡住。比如服务器响应慢,或者网络不好。如果不设置超时,用户可能会一直等,体验很差。设置了超时,超时后会返回错误,你可以给用户一个提示。
创建会话并发送请求
Rcp_Session*session=nullptr;Rcp_Response*response=nullptr;if((session=HMS_Rcp_CreateSession(nullptr,&err))==nullptr){gotoExit;}response=HMS_Rcp_FetchSync(session,request,&err);if(err){gotoExit;}创建会话对象,然后同步发送请求:
HMS_Rcp_CreateSession:创建一个 HTTP 会话。会话就像一个"连接通道"HMS_Rcp_FetchSync:同步发送请求。这个函数会阻塞,直到请求完成或超时
HMS_Rcp_FetchSync是同步的,会阻塞当前线程。如果你在主线程调用,界面会卡住。所以在实际开发中,建议在子线程中调用。
第五步:用 NAPI 封装 C++ 接口
如果想在 ArkTS 中调用 C++ 接口,需要用 NAPI 封装。
EXTERN_C_STARTstaticnapi_valueInit(napi_env env,napi_value exports){napi_property_descriptor desc[]={{"Get",nullptr,Get,nullptr,nullptr,nullptr,napi_default,nullptr},{"GetWithTimeout",nullptr,GetWithTimeout,nullptr,nullptr,nullptr,napi_default,nullptr},{"GetWithTransferRange",nullptr,GetWithTransferRange,nullptr,nullptr,nullptr,napi_default,nullptr}};napi_define_properties(env,exports,sizeof(desc)/sizeof(desc[0]),desc);returnexports;}EXTERN_C_ENDstaticnapi_module demoModule={.nm_version=1,.nm_flags=0,.nm_filename=nullptr,.nm_register_func=Init,.nm_modname="entry",.nm_priv=((void*)0),.reserved={0},};extern"C"__attribute__((constructor))voidRegisterEntryModule(void){napi_module_register(&demoModule);}把 C++ 接口封装成 ArkTS 可以调用的接口。这段代码做了以下事情:
- 定义了三个函数:
Get、GetWithTimeout、GetWithTransferRange - 把这三个函数注册为 ArkTS 可以调用的接口
- 当 ArkTS 加载这个动态库时,会自动调用
Init函数
你不需要完全理解这段代码,只要知道"这是把 C++ 函数暴露给 ArkTS"就行了。
第六步:导出 ArkTS 接口
在Index.d.ts中导出接口:
exportconstGet:(url:string)=>string;exportconstGetWithTimeout:(url:string,connectTimeoutMs:number,transferTimeout:number)=>string;exportconstGetWithTransferRange:(url:string,from:number,to:number)=>string;定义了三个接口:
Get:基础 URL 请求,只传一个 URL,返回响应内容GetWithTimeout:带超时的请求,可以自定义连接超时和传输超时GetWithTransferRange:断点续传请求,可以指定下载的范围
这个文件是 TypeScript 的类型声明文件,告诉 ArkTS “这些函数的参数和返回值是什么类型”。
第七步:在 ArkTS 中调用
importrcpSdkfrom'libentry.so';constkHttpServerAddress="https://httpbin.org/range/100";letres=rcpSdk.Get(kHttpServerAddress);console.info('rcp sdk Get result:',res);导入 C++ 动态库,然后直接调用封装好的接口。libentry.so就是编译出来的动态库文件。
调用方式和普通 ArkTS 函数一样,完全感觉不到底层是 C++ 在执行。
三种请求模式
基础 URL 请求
privategetTokenSyn=async()=>{try{letres=rcpSdk.Get(kHttpServerAddress);this.content=`${kHttpServerAddress}传递成功`;console.info('rcp sdk Get result:',res);}catch(err){this.content=`${kHttpServerAddress}传递失败`+JSON.stringify(err);}}最简单的请求,只传一个 URL。适合请求小数据量的场景,比如获取配置信息、获取用户信息等。
超时请求
privategetTimeoutSyn=async()=>{this.content='waiting for response';try{constresponse=rcpSdk.GetWithTimeout(kHttpServerAddress,this.connectMs,this.transferMs);console.info('timeout--success',JSON.stringify(response));this.content='timeout--success';}catch(err){console.error('timeout--err',JSON.stringify(err));this.content='timeout--err + '+JSON.stringify(err);}}带超时控制的请求。如果在指定时间内没有完成,会抛出错误。适合对响应时间有要求的场景,比如实时数据查询。
断点续传
privategetTransferSyn=async()=>{try{constresp=rcpSdk.GetWithTransferRange(kHttpServerAddress,this.from,this.to);this.content=`${kHttpServerAddress}断点续传成功`;console.info('断点续传成功',resp);}catch(err){this.content=`${kHttpServerAddress}断点续传失败`+JSON.stringify(err);}}断点续传请求,可以指定下载的范围。比如从第 100 字节开始下载,下载到第 200 字节。这在下载大文件时很有用,网络断了可以从断点继续下载。
实际应用场景
远场通信服务在实际开发中有很多用途:
游戏网络请求
// 游戏中用 C++ 发起网络请求,性能更好importrcpSdkfrom'libentry.so';asyncfunctionfetchGameData(apiUrl:string){letresponse=rcpSdk.Get(apiUrl);returnJSON.parse(response);}游戏对性能要求很高,用 C++ 发起网络请求可以减少延迟。比如获取游戏配置、同步游戏状态等。
大文件下载
// 下载大文件,支持断点续传asyncfunctiondownloadFile(url:string,savePath:string){letfrom=0;letto=1024*1024;// 每次下载 1MBwhile(true){try{rcpSdk.GetWithTransferRange(url,from,to);from=to;to+=1024*1024;}catch(err){// 下载完成或出错break;}}}下载大文件时,用断点续传可以提高可靠性。每次下载 1MB,下载完一块再下载下一块。如果网络断了,只需要重新下载当前这一块,不用从头开始。
高性能数据同步
// 用 C++ 处理大量数据同步asyncfunctionsyncData(dataUrl:string){letresponse=rcpSdk.GetWithTimeout(dataUrl,5000,30000);returnprocessResponse(response);}数据同步场景需要高性能,用 C++ 可以更快地处理大量数据。
适用场景
远场通信服务适合以下场景:
- 游戏应用:高性能网络请求
- 音视频应用:流媒体数据传输
- 文件传输:大文件下载、断点续传
- 数据同步:大量数据的同步处理
注意事项
- 权限配置:需要配置 INTERNET 权限,否则网络请求会失败
- 编译配置:需要正确配置 CMakeLists.txt,否则编译会报错
- NAPI 封装:如果要在 ArkTS 中调用,需要 NAPI 封装,这个步骤不能省
- 错误处理:网络请求要处理各种错误情况,比如网络不通、服务器错误、超时等
- 超时设置:根据实际场景设置合理的超时时间,太短容易失败,太长用户体验差
总结
远场通信服务让你用 C++ 发起 HTTP 请求,核心流程:
- 配置编译脚本,引入远场通信 SDK
- 配置网络权限
- 在 C++ 中发起 HTTP 请求
- 用 NAPI 封装 C++ 接口
- 在 ArkTS 中调用封装好的接口
掌握了这些,你就能用 C++ 进行高性能的网络请求开发。
