Cross-platform async IPC crate with multiple messaging patterns.
- Windows
- Linux
- macOS
- Flexible messaging: request-response, broadcast, publish-subscribe, and server-initiated broadcast
- Cross-platform: Built on top of the
interprocesscrate. - Custom codecs: Easily swap out message ser/de formats.
The server is a long-running process that handles incoming connections and acts as a relay for messages between clients.
use std::sync::Arc;use ipceed::{server::IpcServer,MessageHandler,RequestId,Topic,ClientId};use ipceed::codecs::JsonCodec;use serde::{Deserialize,Serialize};#[derive(Clone,Serialize,Deserialize,Debug)]structMyRequest{message:String,}#[derive(Serialize,Deserialize,Debug)]structMyResponse{reply:String,}structMyHandler;#[async_trait::async_trait]impl<C:IpcCodec>MessageHandler<C,MyRequest,MyResponse>forMyHandler{asyncfnhandle_request(&self,id:RequestId,request:&MyRequest) -> Option<MyResponse>{println!("Handling request {}: {:?}", id, request);Some(MyResponse{reply:format!("Echo: {}", request.message),})}asyncfnon_publish(&self,topic:&Topic,_data:Arc<Vec<u8>>){println!("Message published to topic: {}", topic);}asyncfnon_unsubscribe(&self,client_id:ClientId,topic:&Topic){println!("Client {} unsubscribed from topic: {}", client_id, topic);}}#[tokio::main]asyncfnmain() -> Result<(),Box<dyn std::error::Error>>{let handler = Arc::new(MyHandler);let server = IpcServer::<JsonCodec,MyRequest,MyResponse>::new("/tmp/my_ipc_server",
handler,100,// broadcast capacity)?;// Get broadcaster for sending messages to all clientslet broadcaster = server.broadcaster();// Start the server (this blocks)
server.start().await;Ok(())}The client can send requests to the server and await responses.
use ipceed::{client::IpcClient, codecs::JsonCodec};use serde::{Deserialize,Serialize};use std::time::Duration;#[derive(Serialize,Deserialize,Debug)]structMyRequest{message:String,}#[derive(Serialize,Deserialize,Debug)]structMyResponse{reply:String,}#[tokio::main]asyncfnmain() -> Result<(),Box<dyn std::error::Error>>{// Connect to the serverlet(client, _broadcast_rx) = IpcClient::<JsonCodec>::connect::<Vec<u8>>("/tmp/my_ipc_server").await?;// Configure request timeoutlet client = client.set_request_timeout(Duration::from_secs(5));// Request-Responselet request = MyRequest{message:"Hello, server!".to_string(),};let response:MyResponse = client.send_request(request).await?;println!("Response: {:?}", response);Ok(())}The client can subscribe to topics and receive messages published to the topic by other clients or the server.
use ipceed::{client::IpcClient, codecs::JsonCodec};use serde::{Deserialize,Serialize};#[derive(Serialize,Deserialize,Debug)]structTopicMessage{content:String,}#[tokio::main]asyncfnmain() -> Result<(),Box<dyn std::error::Error>>{// Connect to the serverlet(client,mut broadcast_rx) = IpcClient::<JsonCodec>::connect::<Vec<u8>>("/tmp/my_ipc_server").await?;// Subscribe to a topicletmut subscription = client.subscribe::<TopicMessage>("my_topic").await?;// Publish to the topiclet topic_message = TopicMessage{content:"Hello, subscribers!".to_string(),};
client.publish("my_topic", topic_message).await?;// Receive published messageifletSome(received) = subscription.recv().await{println!("Received topic message: {:?}", received);}// Unsubscribe from topic
client.unsubscribe("my_topic").await?;// Listen for broadcast messagesifletSome(broadcast) = broadcast_rx.recv().await{println!("Received broadcast: {:?}", broadcast);}Ok(())}The server can send messages to all connected clients.
use ipceed::server::IpcBroadcastSender;use ipceed::codecs::JsonCodec;asyncfnbroadcast_example(broadcaster:IpcBroadcastSender<JsonCodec>){// Send a broadcast message to all connected clientslet message = "Server announcement: System maintenance in 5 minutes";match broadcaster.broadcast(message){Ok(client_count) => println!("Broadcast sent to {} clients", client_count),Err(e) => eprintln!("Failed to broadcast: {:?}", e),}}Out of the box, ipceed provides the following codecs:
JsonCodec: JSON viaserde_json
You could also rely on other formats by implementing the IpcCodec trait:
use ipceed::codecs::IpcCodec;use ipceed::IpcResult;#[derive(Debug,Clone)]pubstructCustomCodec;implIpcCodecforCustomCodec{fnserialize<T>(value:&T) -> IpcResult<Vec<u8>>whereT: serde::Serialize,{// Custom serialization logicOk(serde_json::to_vec(value)?)}fndeserialize<T>(bytes:&[u8]) -> IpcResult<T>whereT:for<'de> serde::Deserialize<'de>,{// Custom deserialization logicOk(serde_json::from_slice::<T>(bytes)?)}}- Support for additional codecs (MessagePack, Protocol Buffers, etc.)