dart_ipc 2.0.0 copy "dart_ipc: ^2.0.0" to clipboard
dart_ipc: ^2.0.0 copied to clipboard

A cross-platform Inter-Process Communication (IPC) library for Dart that provides efficient communication between processes using native platform mechanisms.

example/lib/main.dart

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';

import 'package:dart_ipc/dart_ipc.dart';
import 'package:json_rpc_2/json_rpc_2.dart';
import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late String _path;

  @override
  void initState() {
    super.initState();

    if (Platform.isWindows) {
      _path = r"\\.\pipe\dart_ipc";
    } else {
      _path = _exampleUnixSocketPath();
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Plugin example app')),
        body: Center(
          child: Row(
            children: [
              TextButton(
                onPressed: () async {
                  final serverSocket = await bind(_path);

                  await for (final socket in serverSocket) {
                    debugPrint(socket.toString());
                    socket.listen(
                      (data) {
                        debugPrint(utf8.decode(data));
                        socket.add(utf8.encode('Hello from Server'));
                      },
                      onDone: () {
                        debugPrint("Server Done");
                      },
                      onError: (e) {
                        debugPrint("Server Error: $e");
                      },
                    );
                  }
                },
                child: const Text("Server"),
              ),
              TextButton(
                onPressed: () async {
                  final socket = await connect(_path);

                  socket.listen(
                    (data) {
                      debugPrint(utf8.decode(data));
                    },
                    onDone: () {
                      debugPrint("Client Done");
                    },
                    onError: (e) {
                      debugPrint("Client Error: $e");
                    },
                  );

                  for (var i = 0; i < 10; i++) {
                    socket.add(utf8.encode("Hello from client1 $i"));
                    await Future.delayed(const Duration(seconds: 1));
                  }
                  await socket.close();
                },
                child: const Text("Client1"),
              ),
              TextButton(
                onPressed: () async {
                  final socket = await connect(_path);

                  socket.listen(
                    (data) {
                      debugPrint(utf8.decode(data));
                    },
                    onDone: () {
                      debugPrint("Client Done");
                    },
                    onError: (e) {
                      debugPrint("Client Error: $e");
                    },
                  );

                  for (var i = 0; i < 10; i++) {
                    socket.add(utf8.encode("Hello from client2 $i"));
                    await Future.delayed(const Duration(seconds: 1));
                  }
                  await socket.close();
                },
                child: const Text("Client2"),
              ),
              TextButton(
                onPressed: () async {
                  final serverSocket = await bind(_path);
                  final httpServer = HttpServer.listenOn(serverSocket);
                  final connectedChannels = httpServer
                      .transform(WebSocketTransformer())
                      .map(IOWebSocketChannel.new);
                  connectedChannels.listen(handleClient);
                },
                child: const Text("JsonRpcServer"),
              ),
              TextButton(
                onPressed: () async {
                  final httpClient = HttpClient()
                    ..connectionFactory =
                        (Uri uri, String? proxyHost, int? proxyPort) {
                          final socket = connect(_path);
                          return Future.value(
                            ConnectionTask.fromSocket(socket, () {}),
                          );
                        };

                  // final webSocket = webSocketConnect();
                  final socket = IOWebSocketChannel.connect(
                    "ws://localhost",
                    customClient: httpClient,
                  );
                  var client = Client(socket.cast<String>());

                  // The client won't subscribe to the input stream until you call `listen`.
                  // The returned Future won't complete until the connection is closed.
                  unawaited(client.listen());

                  // This calls the "count" method on the server. A Future is returned that
                  // will complete to the value contained in the server's response.
                  var count = await client.sendRequest('count');
                  debugPrint('Count is $count');

                  // // Parameters are passed as a simple Map or, for positional parameters, an
                  // // Iterable. Make sure they're JSON-serializable!
                  var echo = await client.sendRequest('echo', {
                    'message': 'hello',
                  });
                  debugPrint('Echo says "$echo"!');

                  // // A notification is a way to call a method that tells the server that no
                  // // result is expected. Its return type is `void`; even if it causes an
                  // // error, you won't hear back.
                  client.sendNotification('count');

                  // If the server sends an error response, the returned Future will complete
                  // with an RpcException. You can catch this error and inspect its error
                  // code, message, and any data that the server sent along with it.
                  try {
                    await client.sendRequest('divide', {
                      'dividend': 2,
                      'divisor': 0,
                    });
                  } on RpcException catch (error) {
                    debugPrint('RPC error ${error.code}: ${error.message}');
                  }
                },
                child: const Text("JsonRpcClient"),
              ),
            ],
          ),
        ),
      ),
    );
  }

  String _exampleUnixSocketPath() {
    const maxPortableUnixSocketPathLength = 100;
    const fileName = "dart_ipc.unix";
    final tempPath = Directory.systemTemp.path;
    final absolutePath = tempPath.endsWith(Platform.pathSeparator)
        ? "$tempPath$fileName"
        : "$tempPath${Platform.pathSeparator}$fileName";

    // Unix domain sockets store the literal path in a small fixed-size field.
    // Prefer the writable temp directory directly, but fall back to a short
    // relative path if a sandboxed temp path is still too long.
    if (utf8.encode(absolutePath).length <= maxPortableUnixSocketPathLength) {
      return absolutePath;
    }

    Directory.current = Directory.systemTemp;
    return fileName;
  }

  void handleClient(WebSocketChannel socket) {
    // The socket is a `StreamChannel<dynamic>` because it might emit binary
    // `List<int>`, but JSON RPC 2 only works with Strings so we assert it only
    // emits those by casting it.
    var server = Server(socket.cast<String>());

    // Any string may be used as a method name. JSON-RPC 2.0 methods are
    // case-sensitive.
    var i = 0;
    server.registerMethod('count', () {
      // Just return the value to be sent as a response to the client. This can
      // be anything JSON-serializable, or a Future that completes to something
      // JSON-serializable.
      return i++;
    });

    // Methods can take parameters. They're presented as a `Parameters` object
    // which makes it easy to validate that the expected parameters exist.
    server.registerMethod('echo', (Parameters params) {
      // If the request doesn't have a "message" parameter this will
      // automatically send a response notifying the client that the request
      // was invalid.
      return params['message'].value;
    });

    // `Parameters` has methods for verifying argument types.
    server.registerMethod('subtract', (Parameters params) {
      // If "minuend" or "subtrahend" aren't numbers, this will reject the
      // request.
      return params['minuend'].asNum - params['subtrahend'].asNum;
    });

    // [Parameters] also supports optional arguments.
    server.registerMethod('sort', (Parameters params) {
      var list = params['list'].asList;
      list.sort();
      if (params['descendint'].asBoolOr(false)) {
        return list.reversed;
      } else {
        return list;
      }
    });

    // A method can send an error response by throwing a `RpcException`.
    // Any positive number may be used as an application- defined error code.
    const divideByZero = 1;
    server.registerMethod('divide', (Parameters params) {
      var divisor = params['divisor'].asNum;
      if (divisor == 0) {
        throw RpcException(divideByZero, 'Cannot divide by zero.');
      }

      return params['dividend'].asNum / divisor;
    });

    // To give you time to register all your methods, the server won't start
    // listening for requests until you call `listen`. Messages are buffered until
    // listen is called. The returned Future won't complete until the connection
    // is closed.
    server.listen();
  }
}
7
likes
150
points
2.37k
downloads

Documentation

API reference

Publisher

verified publishermonkeywie.cn

Weekly Downloads

A cross-platform Inter-Process Communication (IPC) library for Dart that provides efficient communication between processes using native platform mechanisms.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

ffi, win32

More

Packages that depend on dart_ipc