Flutter for OpenHarmony:json_rpc_2 比 REST 更轻量的远程调用协议,实现高效的前后端通信(JSON-RPC 2.0 实现) 深度解析与鸿蒙适配指南
文章摘要 本文介绍了JSON-RPC 2.0协议及其在Dart中的实现库json_rpc_2,适用于轻量级、跨平台的远程调用场景。JSON-RPC 2.0基于JSON,支持多种传输方式(如WebSocket、TCP),广泛应用于以太坊、比特币等区块链节点通信。文章详细解析了协议规范,包括请求、响应、通知和错误的JSON结构,并展示了如何使用json_rpc_2库构建客户端和服务端。此外,还提供了在
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
前言
在现代软件架构中,RPC (Remote Procedure Call) 无处不在。它允许我们像调用本地函数一样调用远程服务器上的函数。虽然 gRPC 和 REST (HTTP/JSON) 十分流行,但在一些特定场景下,JSON-RPC 2.0 依然是不可替代的标准。
- 轻量级:仅依赖 JSON,无须复杂的 Protobuf 编解码或 HTTP Header 开销。
- 传输无关:可以跑在 WebSocket、TCP Socket、甚至串口(Serial Port)上。
- 广泛支持:以太坊(Ethereum)、比特币(Bitcoin)节点通信全部基于 JSON-RPC。
- 简单明了:人眼可读,调试极其方便。
json_rpc_2 是 Google 官方维护的一个 Dart 库,严格遵循 JSON-RPC 2.0 规范,提供了极高质量的 Client 和 Server 实现。
对于 OpenHarmony 开发者,这意味着你可以轻松地用 Dart 构建与底层硬件(如智能家居网关、工控机)通信的客户端,或者搭建一个极简的微服务 API。
一、核心原理与协议规范
1.1 JSON-RPC 2.0 协议详解
JSON-RPC 的消息体极其简洁。
请求 (Request):
{
"jsonrpc": "2.0",
"method": "subtract",
"params": [42, 23],
"id": 1
}
响应 (Response):
{
"jsonrpc": "2.0",
"result": 19,
"id": 1
}
通知 (Notification):
没有 id 字段,服务端收到后不返回任何结果(Fire-and-Forget)。
{
"jsonrpc": "2.0",
"method": "update",
"params": [1, 2, 3, 4, 5]
}
错误 (Error):
{
"jsonrpc": "2.0",
"error": {
"code": -32601,
"message": "Method not found"
},
"id": "1"
}
json_rpc_2 库完全封装了这些 JSON 细节,让你直接面对 Dart 对象编程。
二、核心 API 详解
2.1 客户端 (Client)
客户端需要一个 StreamChannel 来传输数据。这个 Channel 可以来自 web_socket_channel(用于 Web),也可以来自 dart:io 的 Socket(用于 TCP)。
import 'package:json_rpc_2/json_rpc_2.dart';
import 'package:web_socket_channel/io.dart';
void main() async {
// 1. 建立连接
var socket = IOWebSocketChannel.connect('ws://localhost:4321');
// 2. 创建 Client
var client = Client(socket.cast());
// 3. 必须先 listen (启动消息循环)
unawaited(client.listen());
try {
// 4. 发送请求
var result = await client.sendRequest('add', [1, 2]);
print('1 + 2 = $result');
// 5. 发送通知 (无返回值)
client.sendNotification('log', ['Connection established']);
} finally {
await client.close();
}
}

2.2 服务端 (Server)
服务端 API 同样简洁。你可以注册方法来处理请求。
import 'package:json_rpc_2/json_rpc_2.dart';
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_web_socket/shelf_web_socket.dart';
void main() {
var handler = webSocketHandler((webSocket) {
var server = Server(webSocket.cast());
// 注册方法
server.registerMethod('add', (Parameters params) {
var nums = params.asList;
return nums[0] + nums[1];
});
server.registerMethod('subtract', (Parameters params) {
var nums = params.asList;
return nums[0] - nums[1];
});
// 启动监听
server.listen();
});
io.serve(handler, 'localhost', 4321).then((server) {
print('Serving at ws://${server.address.host}:${server.port}');
});
}
2.3 错误处理
json_rpc_2 会自动抛出 RpcException。你可以捕获具体的错误码。
try {
await client.sendRequest('unknown_method');
} on RpcException catch (e) {
if (e.code == RpcException.methodNotFound) {
print('Method not found!'); // Code -32601
} else {
print('Error ${e.code}: ${e.message}');
}
}

三、OpenHarmony 平台适配实战
在鸿蒙系统(尤其是 IoT 设备)中,TCP 通信比 HTTP 更常见且更高效。我们可以使用 Dart 原生的 Socket 来承载 JSON-RPC。
3.1 基于 TCP Socket 的全双工通信
假设我们有一个运行在鸿蒙开发板上的 Dart 服务端,控制 LED 灯。
// lib/rpc_server.dart (运行在开发板)
import 'dart:io';
import 'package:json_rpc_2/json_rpc_2.dart';
import 'package:stream_channel/stream_channel.dart';
void startServer() async {
// 监听 8080 端口
var serverSocket = await ServerSocket.bind(InternetAddress.anyIPv4, 8080);
print('Listening on port 8080...');
await for (var socket in serverSocket) {
// 将 Socket 包装为 StreamChannel<String> (UTF-8)
var channel = jsonDocument.bind(
StreamChannel(socket, socket)
);
var rpcServer = Server(channel);
// 注册控制方法
rpcServer.registerMethod('set_led', (Parameters params) {
bool on = params['on'].asBool; // 获取命名参数
print('Turning LED ${on ? 'ON' : 'OFF'}');
// 硬件操作逻辑: GPIO.output(1, on);
return {'status': 'ok', 'led': on};
});
rpcServer.listen();
}
}
3.2 客户端控制 App (Flutter)
// lib/rpc_client.dart
import 'dart:io';
import 'package:json_rpc_2/json_rpc_2.dart';
import 'package:stream_channel/stream_channel.dart';
class IotController {
Client? _client;
Future<void> connect(String ip) async {
var socket = await Socket.connect(ip, 8080);
// 创建双向通道
var channel = jsonDocument.bind(
StreamChannel(socket, socket)
);
_client = Client(channel);
_client!.listen(); // 启动循环
}
Future<void> toggleLed(bool on) async {
if (_client == null || _client!.isClosed) throw Exception('Not connected');
// 调用远程方法
// 虽然是异步网络请求,写起来就像本地函数调用
try {
var response = await _client!.sendRequest('set_led', {'on': on});
print('Response: $response');
} catch (e) {
print('RPC Error: $e');
}
}
}
这个例子展示了 json_rpc_2 最强大的能力:Transport Agnostic (传输无关性)。只要你能提供一个 StreamChannel,不管是 TCP、WebSocket,甚至是 Bluetooth RFCOMM,它都能跑起来。

四、高级进阶:批量请求 (Batch Request)
JSON-RPC 2.0 支持一次发送多个请求,常用于初始化大量数据。
// 客户端
client.withBatch(() {
client.sendRequest('add', [1, 1]);
client.sendRequest('add', [2, 2]);
client.sendNotification('log', ['Batch test']);
}).then((results) {
// results 包含所有返回结果
print(results); // [2, 4, null]
});
这对于移动网络环境极其友好,减少了 RTT(往返时延)。
五、总结
json_rpc_2 是 Dart 生态中被严重低估的一个库。它虽然看起来简单,但却是构建高可靠、低延迟、跨语言通信系统的基石。
与 gRPC 相比,它无需生成代码,调试只需 print;与 REST 相比,它支持全双工 Notification 推送。
对于 OpenHarmony 开发者,特别是涉及 硬件交互、即时通讯、区块链交互 的场景,JSON-RPC 是你的不二之选。
最佳实践:
- 超时控制:在
sendRequest后加上.timeout(Duration(seconds: 5)),防止网络挂死。 - 错误定义:在服务端统一定义业务错误码(如
-32001代表硬件故障),客户端据此做 UI 提示。
更多推荐




所有评论(0)