鸿蒙HarmonyOS RCP开发:开启高效网络通信新时代

目录

一、RCP 初印象:打破传统网络开发束缚​编辑

二、RCP 与 HTTP 深度剖析:差异中见真章

三、开发实战:构建 RCP 基础网络请求

(一)发送请求:多样方式,随心选择

(二)设置会话 URL 基地址:便捷管理,高效开发

四、高级应用:解锁 RCP 强大功能

(一)多表单提交:复杂场景,轻松应对

(二)双向证书校验:安全通信,保驾护航

(三)DNS 定制设置:灵活配置,精准解析

五、常见问题与解决方案:排雷指南

(一)创建 Session 对象超出上限报错

(二)证书校验失败

(三)DNS 解析异常

六、未来展望:RCP 的无限可能


一、RCP 初印象:打破传统网络开发束缚

在传统的网络开发中,我们常常会遭遇诸多痛点。就拿 HTTP 请求来说,设置复杂,从请求头的配置到请求参数的处理,每一个环节都需要开发者小心翼翼地编写大量代码。而且,在处理复杂业务场景时,比如多表单提交、双向证书校验等,传统的 Network Kit 中 HTTP 请求能力显得力不从心,实现起来困难重重,代码量剧增,开发效率大打折扣 。

而 RCP,即远程通信平台(remote communication platform)的出现,为我们带来了新的曙光。它就像是一位全能的助手,提供了强大的网络数据请求功能。相较于 Network Kit 中 HTTP 请求能力,RCP 在易用性上有着质的飞跃。它采用了更为简洁直观的 API 设计,开发者无需再为繁琐的配置而烦恼,能够更快速地实现网络请求功能。

在功能丰富度方面,RCP 更是展现出了巨大的优势。它支持场景化网络 API,能够根据不同的业务场景提供更贴合需求的解决方案;支持网络代理、自定义 DNS 解析,让网络请求更加灵活可控;还支持自定义证书校验、服务器身份校验等,为网络通信的安全性提供了坚实保障,这些都是传统 HTTP 请求难以企及的。

二、RCP 与 HTTP 深度剖析:差异中见真章

为了让大家更直观地了解 RCP 与 HTTP 的区别,我精心整理了以下表格,从功能分类、功能名称和功能描述三个维度进行对比:

功能分类

功能名称

功能描述

HTTP

RCP

基础功能

发送 PATCH 类型请求

以 PATCH 的方式请求

不支持

支持

基础功能

设置会话中 URL 的基地址

会话中 URL 的基地址将自动加在 URL 前面,除非 URL 是一个绝对的 URL

不支持

支持

基础功能

取消自动重定向

HTTP 请求不会自动重定向

不支持

支持

基础功能

拦截请求和响应

在请求后或响应前进行拦截

不支持

支持

基础功能

取消请求

发送请求前取消、发送请求过程中取消、请求接收后取消

不支持

支持

基础功能

响应缓存

是否使用缓存,请求时优先读取缓存。缓存跟随当前进程生效,新缓存会替换旧缓存

不支持

支持

基础功能

设置响应数据的类型

设置数据以何种方式返回,将要响应的数据类型可设置为 string、object、arraybuffer 等类型

支持

不支持

基础功能

定义允许的 HTTP 响应内容的最大字节数

服务器成功响应时,在获取数据前校验响应内容的最大字节数

支持

不支持

证书验证

自定义证书校验

自定义逻辑校验客户端和服务端的证书,判断是否可以连接

不支持

支持

证书验证

忽略 SSL 校验

在建立 SSL 连接时不验证服务器端的 SSL 证书

不支持

支持

DNS

自定义 DNS 解析

包括自定义 DNS 服务器或静态 DNS 规则

不支持

支持

RCP 特有

捕获详细的跟踪信息

在会话中的 HTTP 请求期间捕获详细的跟踪信息。跟踪有助于调试、性能分析和深入了解通信过程中的数据流

不支持

支持

RCP 特有

数据打点,获取 HTTP 请求的具体数据

HTTP 请求各阶段的定时信息

不支持

支持

从表格中我们可以清晰地看到,RCP 在功能上比 HTTP 更加丰富和强大。例如,在发送 PATCH 类型请求时,RCP 能够轻松实现,而 HTTP 却无能为力。在设置会话中 URL 的基地址方面,RCP 也展现出了独特的优势,为开发者提供了更便捷的方式来管理和维护请求地址 。在证书验证和 DNS 解析等关键领域,RCP 同样表现出色,支持自定义证书校验和 DNS 解析,大大增强了网络通信的安全性和灵活性 。

三、开发实战:构建 RCP 基础网络请求

(一)发送请求:多样方式,随心选择

通过 RCP 模块,我们能够轻松发起各种基础的网络请求,如 GET、POST、HEAD、PUT、DELETE、PATCH、OPTIONS 等。在实际开发中,不同的请求方法有着不同的用途。以 PATCH 请求为例,假设我们有一个用户信息对象 UserInfo,其中包含 userId、userName、userGender 等 10 个字段 。在某个特定页面,根据需求只能修改 userName 字段,此时就可以使用 PATCH 请求来更新局部资源。

实现这一功能的思路并不复杂。首先,我们需要导入 rcp 模块,这是使用 RCP 功能的基础。然后创建 headers,设置可接受的数据内容的类型为 json 字符串,这样服务器就能准确知道我们期望的数据格式 。接着创建 modifiedContent,传入想要修改的内容。之后调用 rcp.createSession () 创建通信会话对象 session,这就像是建立了一条与服务器沟通的通道 。再使用 new rcp.Request () 方法创建请求对象 req,在这个过程中指定请求的 URL、方法(这里是 PATCH)、请求头和请求内容。最后调用 session.fetch () 方法发起请求,并通过 then 和 catch 来处理响应结果和错误信息。

下面是核心代码示例:


// 定义请求头

let headers: rcp.RequestHeaders = {'accept': 'application/json'};

// 定义要修改的内容

let modifiedContent: UserInfo = {'userName': 'xxxxxx'};

const securityConfig: rcp.SecurityConfiguration = {tlsOptions: {tlsVersion: 'TlsV1.3'}};

// 创建通信会话对象

const session = rcp.createSession({ requestConfiguration: { security: securityConfig }});

// 定义请求对象

let req = new rcp.Request('http://example.com/fetch', 'PATCH', headers, modifiedContent);

// 发起请求

session.fetch(req).then((response) => {

Logger.info(`Request succeeded, message is ${JSON.stringify(response)}`);

}).catch((err: BusinessError) => {

Logger.error(`err: err code is ${err.code}, err message is ${JSON.stringify(err)}`);

});

这段代码清晰地展示了如何使用 RCP 模块发起 PATCH 请求,从创建请求头、定义修改内容,到创建会话和请求对象,再到发起请求并处理响应,每一个步骤都有条不紊,让开发者能够轻松实现局部资源的更新。

(二)设置会话 URL 基地址:便捷管理,高效开发

在向服务器发起请求时,会话中 URL 的基地址起着重要的作用,它就像是一个基础的路径前缀。当我们设置了会话中 URL 的基地址后,该请求的最终请求地址将由会话中 URL 的基地址与请求路径共同构建。这使得我们可以将服务器的主机地址与公共路径隔离开来,极大地方便了管理和维护。

例如,我们的项目中可能有多个请求都指向同一个服务器的某个特定路径,如http://api.example.com/v1 。如果每次请求都完整地书写这个地址,不仅繁琐,而且容易出错。通过设置会话 URL 基地址,我们只需要在创建会话时设置一次基地址,后续的请求只需要书写相对路径即可,大大提高了代码的简洁性和可维护性。

实现设置会话 URL 基地址也很简单。我们通过 RCP 模块中的 SessionConfiguration 来进行设置。首先导入 rcp 模块,然后设置 sessionConfig 对象中的 baseAddress 为我们想要的基地址,如http://api.example.com 。最后调用 rcp.createSession () 传入 sessionConfig,创建通信会话对象 session。

核心代码如下:


// 定义sessionConfig对象

const sessionConfig: rcp.SessionConfiguration = {

baseAddress: 'http://api.example.com',

headers: {

'authorization': 'Bearer YOUR_ACCESS_TOKEN',

'content-type': 'application/json'

},

requestConfiguration: {

security: {

tlsOptions: {

tlsVersion: 'TlsV1.3'

}

}

}

};

// 创建通信会话对象,并传入sessionConfig

const session = rcp.createSession(sessionConfig);

在这段代码中,我们不仅设置了基地址,还可以同时设置请求头和其他请求配置,为后续的请求做好全面的准备。通过这种方式,我们可以轻松管理和维护服务器地址与公共路径,让开发过程更加高效和便捷。

四、高级应用:解锁 RCP 强大功能

(一)多表单提交:复杂场景,轻松应对

在开发过程中,我们常常会遇到一些复杂的场景,比如在同页面下有 tab 栏可切换多个 Form 表单组件,但却只有一个提交按钮,这时就需要将各组件下的表单数据一起提交 。这种多表单提交的场景,如果使用传统的 HTTP 请求能力来实现,会面临诸多困难,代码编写也会变得复杂繁琐。

而 RCP 模块中的 MultipartForm 为我们提供了便捷的解决方案。其实现思路是,在创建 session 会话后,通过new rcp.Request()的第四个参数传入 MultipartForm,然后通过rcp.fetch()发起 POST 请求,就可以将多个表单数据携带上传至服务端 。

下面我们来看具体的实现步骤和代码示例。首先,导入 rcp 模块,这是使用 RCP 功能的基础。然后设置请求头类型,比如let headers: rcp.RequestHeaders = {'accept': 'application/json'},这样可以明确告诉服务器我们期望接收的数据格式 。接着配置 HTTP 请求的超时值,例如let configuration: rcp.Configuration = {transfer: {timeout: { connectMs: 60000, transferMs: 60000 }}},合理设置超时值可以避免因网络问题导致请求长时间等待 。同时,还可以设置 HTTP 请求中包含的 cookie,如let cookies: rcp.RequestCookies = { 'name1': 'value1', 'name2': 'value2' },以及设置传输数据范围,像let transferRange: rcp.TransferRange = { from: 100, to: 200 } 。

完成上述设置后,调用rcp.createSession()创建通信会话对象,这就像是搭建了一座与服务器沟通的桥梁 。然后通过new rcp.MultipartForm()设置多表单数据,假设我们有三个表单数据,分别是Form1、Form2和Form3,可以这样设置:


const multiForm = new rcp.MultipartForm({

'Form1': this.name,

'Form2': this.hobbies,

'Form3': {

contentType: 'text/plain',

remoteFileName: 'RemoteFileName',

contentOrPath: '/file/to/Path'

}

});

这里的Form1和Form2分别传入了this.name和this.hobbies,Form3则设置了更详细的信息,包括内容类型、远程文件名和内容或路径 。

最后,使用new rcp.Request()创建请求对象,调用session.fetch()方法发起请求,并处理响应结果。核心代码如下:


// 创建通信会话对象session

const session = rcp.createSession();

// 定义请求对象req

let req = new rcp.Request('https://www.example.com', 'POST', headers, multiForm, cookies, transferRange, configuration);

req.content = multiForm;

// 发起请求

session.fetch(req).then((response) => {

Logger.info(`Request succeeded, message is ${JSON.stringify(response)}`);

}).catch((err: BusinessError) => {

Logger.error(`err: err code is ${err.code}, err message is ${JSON.stringify(err)}`);

});

通过以上步骤和代码,我们就可以轻松实现多表单提交的功能,大大提高了开发效率,降低了代码的复杂度,让复杂的业务场景变得更加容易处理。

(二)双向证书校验:安全通信,保驾护航

在当今的网络环境中,通信安全至关重要。为了验证服务端和客户端之间的身份和数据完整性,确保通信的安全性,我们可以使用 RCP 接口能力实现双向证书校验能力。

双向证书校验就像是在通信双方之间建立了一道坚固的防线,只有双方都通过了对方的身份验证,才能进行安全的通信。它的原理是,在通信过程中,客户端和服务端都需要向对方提供自己的证书,并且验证对方证书的合法性。如果证书验证不通过,通信将无法建立,从而有效防止了中间人攻击和数据被窃取篡改的风险 。

在 RCP 中,实现双向证书校验需要在Configuration接口中进行相关配置。首先,我们需要读取证书内容。可以通过getContext(this).area = 0获取上下文,然后使用context.resourceManager.getRawFileContentSync('baidu.pem')读取证书文件内容,这里的baidu.pem是证书文件名,可根据实际情况进行替换 。

接下来,设置请求参数。创建一个请求对象request,并设置其configuration属性,在security字段中配置证书相关信息。例如:


// 证书内容读取

let context: Context = getContext(this);

const keyPemConent = context.resourceManager.getRawFileContentSync('baidu.pem');

// 通信url地址

let kHttpServerAddress = "https://www.baidu.com";

try {

// 建立通信请求

const session = rcp.createSession();

const request = new rcp.Request(kHttpServerAddress, "GET");

// 设置请求参数

request.configuration = {

security: {

certificate: {

content: keyPemConent,

type: "PEM"

}

}

};

console.info(`configuration: ${JSON.stringify(request.configuration)}`);

// fetch方式获取请求结果

const response = await session.fetch(request);

console.info(`证书校验成功, ${JSON.stringify(response)}`);

let content1 = `${kHttpServerAddress} 证书校验成功` + JSON.stringify(response);

} catch (err) {

console.error(`证书校验失败, ${JSON.stringify(err)}`);

let content1 = `${kHttpServerAddress} 证书校验失败` + JSON.stringify(err);

let e: BusinessError = err as BusinessError;

console.error(`testTag Get push token catch error: ${JSON.stringify(e)}`);

}

在这段代码中,我们首先读取了证书内容keyPemConent,然后在request.configuration中配置了证书的内容和类型。通过这种方式,当客户端向服务端发起请求时,服务端会验证客户端证书的合法性,同时客户端也会验证服务端证书的合法性,从而实现了双向证书校验,为通信安全提供了有力的保障。

(三)DNS 定制设置:灵活配置,精准解析

不同的系统、不同的框架使用的域名解析机制各不相同,当用户使用域名连接系统时,可能会遇到各种问题。而 RCP 模块为我们提供了强大的 DNS 定制设置功能,让我们可以根据自己的需求进行灵活配置。

通过 RCP 模块,我们能够实现对 DNS 的多种定制设置,包括自定义 DNS 服务器、自定义静态 DNS 规则和配置 HTTPS 上的 DNS,这些功能都可以通过DnsConfiguration进行设置 。

在DnsConfiguration中,dnsRules用于配置 DNS 规则。其中,自定义 DNS 服务器(DnsServers)可以指定自定义的 DNS 服务器提供解析服务。比如,我们可以这样设置:


const customDnsServers: rcp.DnsServers = [

{ ip: "8.8.8.8" },

{ ip: "8.8.4.4", port: 53 }

];

const sessionWithCustomDns = rcp.createSession({ requestConfiguration: { dns: { dnsRules: customDnsServers } } });

在这段代码中,我们定义了一个customDnsServers数组,包含了两个自定义 DNS 服务器的地址和端口信息,然后通过rcp.createSession()创建会话时,将这些 DNS 规则配置到请求中 。

自定义静态 DNS(StaticDnsRules)则用于在默认的 DNS 不能正常解析部分域名时,手动添加静态 DNS。添加静态 DNS 后,如果hostname匹配,则优先使用指定的地址。例如:


const staticDnsRules: rcp.StaticDnsRules = [

{ host: "example.com", port: 80, ipAddresses: ["192.168.1.1", "192.168.1.2"] },

{ host: "sub.example.com", port: 443, ipAddresses: ["192.168.2.1"] }

];

这里我们定义了两组静态 DNS 规则,当访问example.com和sub.example.com时,会优先使用指定的 IP 地址进行解析 。

另外,我们还可以配置 HTTPS 上的 DNS(DnsOverHttpsConfiguration),以加密的 HTTPS 协议进行 DNS 解析请求,避免原始 DNS 协议中用户的 DNS 解析请求被窃听或者修改的问题,实现保护用户隐私的目的 。

通过这些 DNS 定制设置功能,我们可以根据不同的网络环境和安全需求,灵活配置 DNS,确保网络请求能够准确、快速地解析域名,为应用的稳定运行提供可靠的网络支持。

五、常见问题与解决方案:排雷指南

在 HarmonyOS RCP 开发过程中,我们可能会遇到各种各样的问题,下面为大家总结一些常见问题及对应的解决方案 。

(一)创建 Session 对象超出上限报错

在使用 RCP 开发时,创建 Session 对象是一个常见的操作。然而,当我们创建的 Session 对象数量超过上限时,就会出现报错。错误码为 1007900994,报错信息为 “Sessions number reached limit” 。

出现这个问题的原因是,RCP 对可创建的 Session 对象数量有一定的限制,最多为 16 个,且无法修改。当我们同时创建多个 session 对象,并且在 session 使用后,没有及时关闭 session 连接,就会导致 session 资源超限,从而在再次创建新的 session 对象时出现报错 。

那么,如何解决这个问题呢?首先,建议使用全局 session 对象,这样可以增加资源复用。例如,我们可以创建一个 SessionManager 类来管理全局 session 对象:


export class SessionManager{

static session: rcp.Session;

static creatSession() : rcp.Session{

if (! SessionManager.session) {

SessionManager.session = SessionManager.session = rcp.createSession({

// 这里可以根据需求配置拦截器等

interceptors: [new ResponseCachingInterceptor(cache)]

});

}

return SessionManager.session

}

}

其次,在 session 使用完成后,一定要及时调用 session.close () 关闭 session,避免资源超限。例如:


async function testInterceptor() {

const session = SessionManager.creatSession();

const response1 = await session.get('https://www.example.com');

let request = new rcp.Request("https://www.example.com", 'GET');

const response2 = await session.fetch(request);

// 使用完session后关闭

session.close();

}

(二)证书校验失败

在涉及到通信安全的场景中,证书校验是非常重要的一环。然而,在开发过程中,我们可能会遇到证书校验失败的问题 。

导致证书校验失败的原因有很多。比如,手机无法正常连接外部网络,这会导致无法获取证书或验证证书的有效性;开发 / 商用证书不支持连接的穿戴设备,也会导致证书校验失败;手机系统时间与当前真实时间偏差过大,如偏差超过 10 分钟,也可能会引发证书校验问题;另外,当前应用的包名和签名与申请证书的包名和签名 SHA256 指纹不一致,或者应用 build.gradle 文件配置的签名文件不正确,同样会导致证书校验失败 。

针对这些问题,我们可以采取以下排查思路和解决方案。首先,检查手机能否正常连接外部网络,可以尝试访问其他网站来确认网络是否正常工作。其次,检查开发 / 商用证书是否支持连接的穿戴设备。然后,检查手机系统时间与当前真实时间是否偏差过大,如果偏差超过 10 分钟,及时调整系统时间 。最后,仔细检查当前应用的包名和签名与申请证书的包名和签名 SHA256 指纹是否一致,以及应用 build.gradle 文件配置的签名文件是否正确。可以通过以下命令查看签名后应用的包名和签名证书指纹信息:

查看签名后应用的包名:手机连接电脑后,打开需要查询的应用,在电脑打开 CMD(电脑已安装 adb),输入 “adb shell dumpsys window | findstr mCurrentFocus”,显示的结果中,红色框内的就是当前应用的包名 。

查看签名后应用的签名证书指纹信息:电脑打开 CMD,输入 “keytool -list -printcert -jarfile 应用 apk 的绝对路径”,显示的结果中,红色框内就是应用的 SHA256 指纹信息。如果是鸿蒙应用(.hap),需要先解压 hap 文件,然后查看里面 apk 的签名信息 。

同时,把证书(.cer 结尾)内容用 Base64 解码就可以看到证书内容,可以在三方网站进行转码,如 bejson。解码后可以查看证书中应用的包名和指纹 。

(三)DNS 解析异常

在 RCP 开发中,DNS 解析异常也是一个常见的问题。当出现 DNS 解析异常时,会导致无法正确解析域名对应的 IP 地址,从而影响网络请求的正常进行 。

造成 DNS 解析异常的原因主要有以下几点。网络连接问题是一个常见原因,如果网络连接不稳定或者中断,就可能导致 DNS 解析失败;DNS 服务器故障也会引发 DNS 解析异常,比如 DNS 服务器负载过高、配置错误等;本地 DNS 缓存问题也不容忽视,当本地 DNS 缓存中存在错误的解析记录时,就会导致 DNS 解析异常 。

为了解决 DNS 解析异常问题,我们可以按照以下步骤进行排查和解决。首先,检查网络连接是否正常,可以尝试访问其他网站来确认网络是否正常工作。如果网络连接正常,接着清除本地 DNS 缓存。在 Windows 系统中,可以通过命令行输入 “ipconfig /flushdns” 来清除本地 DNS 缓存;在 Mac 系统中,可以通过命令行输入 “sudo killall -HUP mDNSResponder” 来清除 DNS 缓存 。如果清除 DNS 缓存后问题仍然存在,可以尝试更换使用其他的 DNS 服务器。常用的公共 DNS 服务器有谷歌的 8.8.8.8 和 8.8.4.4,OpenDNS 的 208.67.222.222 和 208.67.220.220,腾讯的 119.29.29.29 和 182.254.116.116 等 。另外,如果是自己管理的域名,需要确保域名的 DNS 配置正确,可以登录域名注册商的管理界面,检查域名解析记录是否正确设置 。如果以上方法都无法解决 DNS 解析异常,可以联系网络服务提供商寻求帮助,他们可能需要进一步检查网络配置或提供技术支持 。

六、未来展望:RCP 的无限可能

随着鸿蒙系统的不断发展,RCP 也将迎来更加广阔的应用前景 。在未来,物联网领域将是 RCP 大展身手的重要舞台。想象一下,家中的各种智能设备,如智能音箱、智能摄像头、智能家电等,都通过鸿蒙系统连接在一起,而 RCP 则负责这些设备之间高效、安全的网络通信 。它能够确保设备之间的数据传输稳定可靠,让用户可以通过手机或其他智能终端,轻松控制家中的一切设备,实现真正的智能家居生活 。

在工业互联网领域,RCP 同样有着巨大的潜力。工厂中的各种设备,如机床、机器人、传感器等,需要进行实时的数据交互和协同工作。RCP 可以满足工业场景对网络通信的高要求,实现设备之间的精准控制和高效协作,提高生产效率,降低生产成本,助力工业 4.0 的发展 。

对于开发者来说,RCP 为我们提供了一个强大的工具,让我们能够在鸿蒙生态中创造出更多创新的应用 。希望大家能够积极探索 RCP 在更多复杂场景中的应用,不断挖掘它的潜力。相信在我们的共同努力下,RCP 将为鸿蒙生态的网络通信开发贡献更多的力量,让鸿蒙系统在未来的科技发展中绽放出更加耀眼的光芒 。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容