81 个版本
0.19.2 | 2024 年 6 月 1 日 |
---|---|
0.19.0 | 2024 年 1 月 14 日 |
0.18.0 | 2023 年 9 月 4 日 |
0.17.0 | 2023 年 5 月 8 日 |
0.0.3 | 2014 年 11 月 23 日 |
#33 在 网络编程
72,222 每月下载量
用于 37 个 crate (16 直接)
2MB
42K SLoC
capnp-rpc-rust
这是 Cap'n Proto 远程过程调用协议的 一级 实现。它是原始 C++ 实现 的相当直接的翻译。
定义接口
首先,确保您的系统上已安装 capnp
可执行文件,并且您在 Cargo.toml
的 build-dependencies
部分中包含 capnpc
crate。然后,在一个名为 foo.capnp
的文件中,定义您的接口
@0xa7ed6c5c8a98ca40;
interface Bar {
baz @0 (x :Int32) -> (y :Int32);
}
interface Qux {
quux @0 (bar :Bar) -> (y :Int32);
}
现在您可以在 build.rs
文件中调用模式编译器,如下所示
fn main() {
::capnpc::CompilerCommand::new().file("foo.capnp").run().unwrap();
}
您可以将生成的代码包含到项目中,如下所示
pub mod foo_capnp {
include!(concat!(env!("OUT_DIR"), "/foo_capnp.rs"));
}
调用 RPC 对象上的方法
对于每个定义的接口,生成的代码都包含一个可以用来调用接口方法的 Client
结构。例如,以下代码调用了 Bar.baz()
方法
fn call_bar(client: ::foo_capnp::bar::Client)
-> Box<Future<Item=i32, Error=::capnp::Error>>
{
let mut req = client.baz_request();
req.get().set_x(11);
Box::new(req.send().promise.and_then(|response| {
Ok(response.get()?.get_y())
}))
}
bar::Client
是对可能远程的 Bar
对象的引用。Cap'n Proto RPC 运行时跟踪任何给定时间点此类引用的数量,并在没有此类引用时自动释放对象。
实现接口
生成的代码还包括每个接口的 Server
特性。要创建一个具有 RPC 功能的对象,您必须实现该特性。
struct MyBar {}
impl ::foo_capnp::bar::Server for MyBar {
fn baz(&mut self,
params: ::foo_capnp::bar::BazParams,
mut results: ::foo_capnp::bar::BazResults)
-> Promise<(), ::capnp::Error>
{
// `pry!` is defined in capnp_rpc. It's analogous to `try!`.
results.get().set_y(pry!(params.get()).get_x() + 1);
Promise::ok(())
}
}
然后你可以将你的对象转换为能力客户端,如下所示
let client: foo_capnp::bar::Client = capnp_rpc::new_client(MyBar {});
这个新的 client
现在可以跨网络传输。当你构建一个 RpcSystem
时,你可以将其用作引导能力,你还可以将其作为 RPC 方法参数和结果传递。
异步方法
生成的 Server
特性的方法返回类型为 Promise<<(), ::capnp::Error>
的值。一个 Promise
要么是一个立即值,由 Promise::ok()
或 Promise::err()
构造,或者它是一个由 Promise::from_future()
构造的 Future
的包装器。一旦发生两件事,结果就会发送回方法调用者
- 已删除
Results
结构。 - 返回的
Promise
已解析。
通常(1)发生在(2)之前。
以下是一个不立即返回的方法实现示例
struct MyQux {}
impl ::foo_capnp::qux::Server for MyQux {
fn quux(&mut self,
params: ::foo_capnp::qux::QuuxParams,
mut results: ::foo_capnp::wux::QuuxResults)
-> Promise<(), ::capnp::Error>
{
// Call `baz()` on the passed-in client.
let bar_client = pry!(pry!(params.get()).get_bar());
let mut req = bar_client.baz_request();
req.get().set_x(42);
Promise::from_future(req.send().promise.and_then(move |response| {
results.get().set_y(response.get()?.get_y());
Ok(())
}))
}
}
同一对象上的多个 quux
调用可以同时激活,并且它们不需要按调用的顺序返回。
进一步阅读
- hello world 示例演示了一个基本的请求/回复模式。
- 计算器示例演示了如何使用 promise 管道化。
- pubsub 示例显示了即使没有方法的接口也是有用的。
- Sandstorm 原始 API 示例应用显示了 Sandstorm 如何让你使用 Cap'n Proto 而不是 HTTP 来编写 Web 应用程序。
依赖项
~0.8–1.1MB
~20K SLoC