Flutter JSON RPC通信插件general_json_rpc的使用
Flutter JSON RPC通信插件general_json_rpc的使用
GeneralJsonRpc
GeneralJsonRpc 是一个实现了 JSON-RPC v2.0 的包,其目的是简化通过网络调用方法和交换数据。
该包专注于将 JSON-RPC 消息编码和解码为字节,以便使用任何协议进行发送和接收。
快速指南
在这个指南中,你将创建一个服务器端和客户端应用程序,通过 TCP 套接字调用方法。
让我们开始:
-
首先在服务器端我们定义了三个方法:
sum
、print
和quit
。sum
方法接收数字列表并返回它们的总和。print
方法接收一个名为message
的参数并在服务器端打印其内容。quit
方法通过执行exit(0)
结束应用程序。
import 'dart:io';
import 'package:general_json_rpc/general_json_rpc.dart';
void main() {
server();
client();
}
服务器端代码
void server() async {
final server = await ServerSocket.bind(InternetAddress.anyIPv4, 8081);
print('[server] Server is running on port 8081');
// 创建 MethodRunner 来定义 RPC 方法
final runner = MethodRunner();
// 现在定义三个方法
runner.register<int>('sum', (numbers) => numbers.reduce((a, b) => a + b));
runner.register<void>('print', (p) => print(p['message']));
runner.register('quit', (_) {
print('[server] Quit');
exit(0);
});
// 现在监听新客户端
await for (final Socket client in server) {
print('[server] new client');
client.listen(
(bytes) async {
// 将字节转换为 RpcObject
final rpcObject = RpcObject.decode(bytes);
// 处理不同的情况
final response = await RpcObject.auto(rpcObject, methodRunner: runner);
// 如果响应不为空,则将其转换为字节并发送给客户端
if (response != null) client.add(response.encode());
},
);
}
}
客户端代码
void client() async {
print('[client] connecting...');
final client = await Socket.connect(InternetAddress.loopbackIPv4, 8081);
print('[client] connected!');
// 创建控制器以帮助发送请求和响应
final controller = RpcController();
// 使用控制器发送请求和响应
controller.sendEvent.addListener(
// 在发送之前对 rpcMessage 进行编码
(rpcMessage) => client.add(rpcMessage.encode()),
);
// 监听消息
client.listen(
(bytes) async {
// 将字节转换为 RpcObject
final rpcObject = RpcObject.decode(bytes);
// 处理 rpcObject
RpcObject.auto(rpcObject, controller: controller);
},
);
// 现在首先请求 `sum` 方法
// 我们将传递一个包含 1、2、3 的数字列表
// sum 将返回 Future<int>
// 可以通过监听 RpcError 来处理错误
controller.request<int>('sum', [1, 2, 3]).then((result) {
print('[client] sum result: $result');
}).onError<RpcError>((error, _) {
print('[client] error: ${error.message}');
});
// ============================= //
// 现在调用 `print` 方法,不期望返回值
controller.notify(
'print',
{
'message': 'A message to be printed on the server side by the client',
},
);
// ============================= //
// 在 5 秒后关闭服务器,调用 `quit` 方法
// 不期望返回值,因此我们将发送一个 RPC 通知
await Future.delayed(
const Duration(seconds: 5),
() => controller.notify('quit'),
);
}
完整示例代码
import 'dart:io';
import 'package:general_json_rpc/general_json_rpc.dart';
void main() async {
server();
client();
}
void server() async {
final server = await ServerSocket.bind(InternetAddress.anyIPv4, 8081);
print('[server] Server is running on port 8081');
// 创建 MethodRunner 来定义 RPC 方法
final runner = MethodRunner();
// 现在定义三个方法
runner.register<int>('sum', (numbers) => numbers.reduce((a, b) => a + b));
runner.register<void>('print', (p) => print(p['message']));
runner.register<void>('quit', (_) => exit(0));
// 现在监听新客户端
await for (final Socket client in server) {
print('[server] new client');
client.listen(
(bytes) async {
// 将字节转换为 RpcObject
final rpcObject = RpcObject.decode(bytes);
// 处理不同情况
// 我们将处理请求和通知
// 请求有返回值而通知没有
// 我们将使用 [onRequestAll] 参数来处理两者
// 我们将使用 runner.executeRequest 作为回调
// handle 将返回一个 Future 的可空 RpcObject,这是当前请求的响应(如果有)
final response = await RpcObject.handle(
rpcObject,
onRequestAll: runner.executeRequest,
);
// 如果响应不为空,则将其转换为字节并发送给客户端
if (response != null) client.add(response.encode());
},
);
}
}
void client() async {
print('[client] connecting...');
final client = await Socket.connect(InternetAddress.loopbackIPv4, 8081);
print('[client] connected!');
// 现在首先请求 `sum` 方法
// 我们期望返回值
// 因此我们将发送一个 RPC 请求
// 我们将传递一个包含 1、2、3 的数字列表
final request = RpcRequest.create('sum', [1, 2, 3]);
// 现在将请求发送到服务器
// 首先使用 `encode()` 方法进行编码然后发送
client.add(request.encode());
// ============================= //
// 现在调用 `print` 方法
// 我们不期望返回值
// 因此我们将发送一个 RPC 通知
final request2 = RpcRequest.notify('print', {});
// 我创建了一个空的 Map 作为参数
// 为了向你展示如何向请求添加额外的参数
// 我将定义键 `message` 并添加我的消息
request2['message'] =
'A message to be printed on the server side by the client';
// 现在编码并发送通知请求
client.add(request2.encode());
// ============================= //
// 现在通过调用 `quit` 方法在 5 秒后关闭服务器
// 我们不期望返回值
// 因此我们将发送一个 RPC 通知
client.add(RpcRequest.notify('quit').encode());
}
监听响应
首先,我们需要在客户端处理响应。
client.listen(
(bytes) {
final rpcObject = RpcObject.decode(bytes);
RpcObject.handle(
rpcObject,
onResponse: RpcResponseManager.global.handleResponse,
);
},
);
现在我们在全局 RpcResponseManager
对象上监听并处理任何响应。
现在让我们处理 sum
方法的结果。
final request = RpcRequest.create('sum', [1, 2, 3]);
client.add(request.encode());
request.waitForResponse().then((result) {
print('[client] sum result: $result');
}).onError<RpcError>((error, _) {
print('[client] error: ${error.message}');
});
你也可以这样处理:
final sum = await request.waitForResponse();
不要忘记我们发送了一个
quit
方法的通知来结束应用。 但现在我们的应用需要等待结果返回,所以我们可以在接收结果后再发送它或注释掉它。
request.waitForResponse().then((result) {
print('[client] sum result: $result');
client.add(RpcRequest.notify('quit').encode());
}).onError<RpcError>((error, _) {
print('[client] error: ${error.message}');
});
更多关于Flutter JSON RPC通信插件general_json_rpc的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter JSON RPC通信插件general_json_rpc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
general_json_rpc
是一个用于在 Flutter 中实现 JSON-RPC 通信的插件。JSON-RPC 是一种轻量级的远程过程调用 (RPC) 协议,它使用 JSON 格式来编码请求和响应。
以下是如何在 Flutter 项目中使用 general_json_rpc
插件的基本步骤:
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 general_json_rpc
插件的依赖:
dependencies:
flutter:
sdk: flutter
general_json_rpc: ^1.0.0 # 请使用最新版本
然后运行 flutter pub get
来安装依赖。
2. 创建 JSON-RPC 客户端
接下来,你可以创建一个 JSON-RPC 客户端来与服务器进行通信。
import 'package:general_json_rpc/general_json_rpc.dart';
import 'package:http/http.dart' as http;
class JsonRpcClient {
final String url;
final JsonRpcClientChannel channel;
JsonRpcClient(this.url)
: channel = JsonRpcClientChannel(url, httpClient: http.Client());
Future<dynamic> call(String method, [dynamic params]) async {
final response = await channel.sendRequest(method, params);
return response.result;
}
}
3. 使用 JSON-RPC 客户端进行通信
现在你可以使用 JsonRpcClient
来发送 JSON-RPC 请求并处理响应。
void main() async {
final client = JsonRpcClient('https://example.com/jsonrpc');
try {
final result = await client.call('echo', {'message': 'Hello, JSON-RPC!'});
print('Response: $result');
} catch (e) {
print('Error: $e');
}
}
4. 处理错误
JSON-RPC 协议允许服务器返回错误响应。你可以通过捕获异常来处理这些错误。
void main() async {
final client = JsonRpcClient('https://example.com/jsonrpc');
try {
final result = await client.call('nonexistent_method');
print('Response: $result');
} on JsonRpcError catch (e) {
print('JSON-RPC Error: ${e.code} - ${e.message}');
} catch (e) {
print('Error: $e');
}
}
5. 使用自定义 HTTP 客户端
如果你需要使用自定义的 HTTP 客户端(例如,处理认证或代理),你可以通过 httpClient
参数传递给 JsonRpcClientChannel
。
import 'package:http/http.dart' as http;
void main() async {
final httpClient = http.Client();
final client = JsonRpcClient('https://example.com/jsonrpc', httpClient: httpClient);
try {
final result = await client.call('echo', {'message': 'Hello, JSON-RPC!'});
print('Response: $result');
} catch (e) {
print('Error: $e');
} finally {
httpClient.close();
}
}
6. 处理批量请求
general_json_rpc
还支持批量请求,你可以一次性发送多个请求并接收多个响应。
void main() async {
final client = JsonRpcClient('https://example.com/jsonrpc');
try {
final responses = await client.channel.sendBatch([
JsonRpcRequest(method: 'echo', params: {'message': 'Hello, JSON-RPC!'}),
JsonRpcRequest(method: 'add', params: [1, 2]),
]);
for (var response in responses) {
print('Response: ${response.result}');
}
} catch (e) {
print('Error: $e');
}
}
7. 处理通知
JSON-RPC 还支持通知(即不需要响应的请求)。你可以使用 sendNotification
方法来发送通知。
void main() async {
final client = JsonRpcClient('https://example.com/jsonrpc');
try {
await client.channel.sendNotification('notify', {'message': 'Hello, JSON-RPC!'});
print('Notification sent');
} catch (e) {
print('Error: $e');
}
}