#thread #channel #sync #message-passing #server-client

ump-ng

线程/任务通信的微消息传递库

1 个不稳定版本

0.1.0 2023年10月2日

#21 in #message-passing


用于 2 crate

0BSD 许可证

24KB
213

微消息传递库

ump-ng crate 是一个简单的客户端/服务器消息传递库,用于进程内通信。其主要目的是允许跨异步/非异步通信(对于服务器和客户端端点)。

ump-ng 与 ump 类似,但它具有单向消息传递操作。


lib.rs:

ump-ng(下一代微消息传递)是一个在线程/任务之间传递消息的库。它与 ump 库类似,但增加了单向消息传递原语。

ump(-ng) 的主要目的是创建简单的 RPC 类设计,但是在进程内的线程/任务之间,而不是在网络上的进程之间。

高级使用概述

应用程序调用 channel 来创建一个由 ServerClient 组成的连接对。

服务器调用 [Server::wait()]/[Server::async_wait()],它阻塞并等待来自客户端的消息。

客户端(在单独的线程或任务中)调用 [Client::post()] 向服务器发送单向消息,或 [Client::req()]/ [Client::areq()] 向服务器发送消息并等待回复。

服务器的 wait 调用返回一个 post 消息或一个包含消息和用于向客户端发送回复的 ReplyContextrequest 消息。

在处理完应用程序定义的消息后,服务器必须在返回的回复上下文对象上调用 [ReplyContext::reply()],以向客户端返回回复消息。

通常情况下,服务器会再次调用wait以等待来自客户端的下一个消息。

客户端收到来自服务器的回复并对其进行处理。

示例

use std::thread;

use ump_ng::{channel, MsgType};

let (server, client) = channel::<String, String, String, ()>();

let server_thread = thread::spawn(move || {
  // Wait for data to arrive from a client
  loop {
    println!("Server waiting for message ..");
    match server.wait().unwrap() {
      MsgType::Put(data) => {
        println!("Server received Put: '{}'", data);
      }
      MsgType::Request(data, rctx) => {
        println!("Server received Request: '{}'", data);

        // Process data from client

        // Reply to client
        let reply = format!("Hello, {}!", data);
        println!("Server replying '{}'", reply);
        rctx.reply(reply);
        break;
      }
    }
  }

  println!("Server done");
});

let msg = String::from("Client");
println!("Client putting '{}'", msg);
let reply = client.post(msg).unwrap();

let msg = String::from("Client");
println!("Client requesting '{}'", msg);
let reply = client.req(msg).unwrap();
println!("Client received reply '{}'", reply);

println!("Client done");

server_thread.join().unwrap();

在实际应用中,send/reply类型可能是用于指示命令/返回类型及其相关数据的枚举(enum)。在channel的第三个类型参数是一个错误类型,可以用于明确地将错误传递回发送者。

语义

有一些可能有用的语义特性值得了解,但其中一些应该谨慎使用。本节将描述一些你可以信赖的语义,以及一些你应该小心依赖的语义。

稳定的不变量

这些是在未来版本中不应改变的行为。

  • 回复上下文与Server上下文无关。这对于服务器线程来说有一些有用的含义,因为服务器线程会创建单独的线程来处理消息并返回回复:当有客户端正在等待回复时,服务器可以安全地终止(隐含:当有回复上下文正在传输时,服务器可以安全地终止)。
  • 克隆的客户端与其原始客户端配对,但在其他所有方面,克隆和原始客户端都是相互独立的。
  • 客户端可以被移动到新的线程。
  • 可以组合任何同步/异步服务器/客户端的排列。当可用时,async代码必须使用异步方法变体。

不稳定的变量

这些是在当前版本中你可以信赖会工作,但它们只是当前实现的一个副作用。如果可能,请避免依赖这些。

  • 单个客户端可以从两个不同的线程中使用。如果将Client对象放入Arc中,克隆并传递给另一个线程/任务,则克隆和原始对象可以同时使用。在将来,这可能不允许。建议创建客户端的新克隆。
  • Put/Request消息按照它们添加到队列的顺序到达。在未来的版本中,一种类型可能比另一种类型具有更高的优先级。

依赖项

~1.1–6MB
~26K SLoC