entao_jsonrpc 1.0.5 copy "entao_jsonrpc: ^1.0.5" to clipboard
entao_jsonrpc: ^1.0.5 copied to clipboard

JSON RPC 2.0 for dart language.

JSON RPC 2.0 for dart language #

ONLY JSON RPC 2.0 protocol implemented. NO transport dependency.

Server Side #

  • Register method use server.addAction().
  • When server transport receive a text packet, call server.onRecvText().
  • errorRpc() will raise an exception with 'RpcError', this will response to client.
  • RpcAction.context, indicate whether a method need RpcContext parameter.
  • RpcAction.expand, indicate whether expand all parameters when invoke a method.

Client Side #

  • RpcClient.request() invoke server method which has a response
  • RpcClient.notify() invoke server method which has NO response
  • RpcClient.remote() with a transport callback, invoke server method which has a response immediately.
    it can be used on http request or blocked tcp connection.
  • When client transport receive a text packet, call client.onRecvText().

Usage #

  • Server define methods, and register them.
String echoIndex(String name, int age) {
  return "echoIndex: $name, $age";
}

String echoName({required String name, required int age}) {
  return "echoName: $name, $age";
}

RpcServer server = RpcServer();
server.addAction(RpcAction("echoName", echoName));
server.addAction(RpcAction("echoIndex", echoIndex));
// when transport receive text packet, give it to rpc server
server.onRecvText(jsonPacket);
  • Client invoke remote method over any transport.
RpcClient client = RpcClient();
// 'sender' is transport, it's like this:  FutureOr<bool> Function(String text)
// it can implements by TCP/UDP/WebSocket/Http etc.
Object? result = await client.request(sender, "echoName", map: {"name": "entao", "age": 33} );
Object? resultIndex = await client.request(sender, "echoIndex", list: ["tom", 99] );
// transport over HTTP or blocked tcp like this:
Object? result = await RpcClient.remote("echoName", map: {"name": "entao", "age": 33}, transport: (jsonText){
  String s = http.post(uri: '...', body: jsonText);
  return s;
});

Example #

Full code at 'example/udp_example.dart'

  • Server define methods
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:entao_jsonrpc/entao_jsonrpc.dart';

String echoIndex(String name, int age) {
  return "echoIndex: $name, $age";
}

String echoName({required String name, required int age}) {
  return "echoName: $name, $age";
}

String echoVoid() {
  return "echoVoid: void";
}

String echoContext(RpcContext context) {
  return "echoContext: ${context.request.params}";
}

String echoContextParams(RpcContext context, dynamic params) {
  return "echoContextParams: $params";
}

// 'RpcContext context' always position first, when RpcAction.context = true
String echoNameWithContext(RpcContext context, {required String name, required int age}) {
  return "echoNameWithContext: $name, $age";
}

  • Server prepare UDP socket.
RpcServer server = RpcServer();
const int SERVER_PORT = 20000;

Future<RawDatagramSocket> startServer([int port = SERVER_PORT]) async {
  RawDatagramSocket serverSocket = await RawDatagramSocket.bind(InternetAddress.loopbackIPv4, port);
  serverSocket.listen((RawSocketEvent e) async {
    switch (e) {
      case RawSocketEvent.closed:
      case RawSocketEvent.readClosed:
      case RawSocketEvent.write:
        return;
      case RawSocketEvent.read:
        Datagram? d = serverSocket.receive();
        if (d != null) {
          String? response = await server.onRecvText(utf8.decode(d.data));
          if (response != null) {
            serverSocket.send(utf8.encode(response), d.address, d.port);
          }
        }
    }
  });
  return serverSocket;
}
  • Server register methods
void prepareServerActions() {
  // register actions on server side.
  // if context parameter is true, the first argument is 'RpcContext context'
  server.addAction(RpcAction("echoName", echoName, context: false, expand: true));
  // default, context=false, expand=true
  server.addAction(RpcAction("echoIndex", echoIndex));

  // expand is ignored when no result (null) received
  server.addAction(RpcAction("echoVoid", echoVoid, context: false));
  server.addAction(RpcAction("echoContext", echoContext, context: true, expand: false));
  server.addAction(RpcAction("echoContextParams", echoContextParams, context: true, expand: false));
  // ONLY expand parameter named 'name' OR 'age'
  server.addAction(RpcAction("echoNameWithContext", echoNameWithContext, context: true, expand: true, names: {"name", "age"}));
} 
  • Client prepare UDP socket
RpcClient client = RpcClient();

Future<RawDatagramSocket> startClient() async {
  RawDatagramSocket clientSocket = await RawDatagramSocket.bind(InternetAddress.loopbackIPv4, 0);
  clientSocket.listen((RawSocketEvent e) {
    switch (e) {
      case RawSocketEvent.closed:
      case RawSocketEvent.readClosed:
      case RawSocketEvent.write:
        return;
      case RawSocketEvent.read:
        Datagram? d = clientSocket.receive();
        if (d != null) {
          client.onRecvText(utf8.decode(d.data));
        }
    }
  });
  return clientSocket;
} 
  • Client Invoke Remote Methods.

Future<void> clientInvokes(RpcTextSender sender) async {
  // named arguments
  Object? result = await client.request(sender, "echoName", map: {"name": "entao", "age": 33}, timeoutSeconds: 1);
  logRpc.d("Result echoName: ", result);
  // 2025-11-14 09:14:02.815 D RPC: Result echoName:  echoName: entao, 33

  // positioned arguments
  Object? resultIndex = await client.request(sender, "echoIndex", list: ["tom", 99], timeoutSeconds: 1);
  logRpc.d("Result echoIndex: ", resultIndex);
  // 2025-11-14 09:14:02.818 D RPC: Result echoIndex:  echoIndex: tom, 99

  // no arguments
  Object? resultEchoVoid = await client.request(sender, "echoVoid", timeoutSeconds: 1);
  logRpc.d("Result echoVoid: ", resultEchoVoid);
  // 2025-11-14 09:14:02.818 D RPC: Result echoVoid:  echoVoid: void

  // with RpcContext argument
  Object? resultEchoContext = await client.request(sender, "echoContext", list: [1, 2, 3], timeoutSeconds: 1);
  logRpc.d("Result echoContext: ", resultEchoContext);
  // 2025-11-14 09:14:02.818 D RPC: Result echoContext:  echoContext: [1, 2, 3]

  // with RpcContext argument and raw parameters result
  Object? resultEchoContextParams = await client.request(sender, "echoContextParams", map: {"a": 1, "b": 2}, timeoutSeconds: 1);
  logRpc.d("Result echoContextParams: ", resultEchoContextParams);
  // 2025-11-14 09:14:02.819 D RPC: Result echoContextParams:  echoContextParams: {a: 1, b: 2}

  // with RpcContext argument and raw parameters result
  Object? resultEchoNameWithContext = await client.request(sender, "echoNameWithContext", map: {"name": "Jerry", "age": 3, "addr": "USA"}, timeoutSeconds: 1);
  logRpc.d("Result echoNameWithContext: ", resultEchoNameWithContext);
  // 2025-11-14 09:14:02.820 D RPC: Result echoNameWithContext:  echoNameWithContext: Jerry, 3
}

  • The Main function
void main() async {
  prepareServerActions();
  RawDatagramSocket serverSocket = await startServer(SERVER_PORT);

  RawDatagramSocket clientSocket = await startClient();

  await clientInvokes((String text) {
    int n = clientSocket.send(utf8.encode(text), InternetAddress("127.0.0.1"), SERVER_PORT);
    return n > 0;
  });

  Future.delayed(Duration(seconds: 1));
  serverSocket.close();
  clientSocket.close();
} 
  • Log on/off
logRpc.off();  // rpc log off
logRpc.on(level: LogLevel.error) // only errors will output 
0
likes
110
points
40
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

JSON RPC 2.0 for dart language.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

entao_lint, entao_log

More

Packages that depend on entao_jsonrpc