Expand description
§RPC: Request/Response & Fire-and-Forget
RecentIP supports two RPC patterns:
- Request/Response: Client sends request, server sends response
- Fire-and-Forget: Client sends request, no response expected
§Request/Response
§Client Side
use recentip::prelude::*;
#[tokio::main]
async fn main() -> Result<()> {
let someip = recentip::configure()
.sd_unicast("192.168.1.100".parse().unwrap())
.sd_multicast_group("239.255.255.250".parse().unwrap())
.start().await?;
let found_service = someip.find(0x1234).await?;
let method = MethodId::new(0x0001).unwrap();
// Synchronous call - waits for response
let response = found_service.call(method, b"request data").await?;
match response.return_code {
ReturnCode::Ok => println!("Success: {:?}", response.payload),
code => println!("Error: {:?}", code),
}
Ok(())
}§Server Side
use recentip::prelude::*;
use recentip::handle::ServiceEvent;
#[tokio::main]
async fn main() -> Result<()> {
let someip = recentip::configure()
.sd_unicast("192.168.1.100".parse().unwrap())
.sd_multicast_group("239.255.255.250".parse().unwrap())
.start().await?;
let mut offering = someip
.offer(0x1234, InstanceId::Id(0x0001))
.version(1, 0)
.start()
.await?;
while let Some(event) = offering.next().await {
if let ServiceEvent::Call { method, payload, responder, .. } = event {
// Process based on method ID
let response = match method.value() {
0x0001 => process_get_status(&payload),
0x0002 => process_set_value(&payload),
_ => b"unknown method".to_vec(),
};
responder.reply(&response)?;
}
}
Ok(())
}
fn process_get_status(_payload: &[u8]) -> Vec<u8> {
b"status: OK".to_vec()
}
fn process_set_value(_payload: &[u8]) -> Vec<u8> {
b"value set".to_vec()
}§Fire-and-Forget
For one-way messages where no response is needed (e.g., notifications, logging):
§Client Side
use recentip::prelude::*;
#[tokio::main]
async fn main() -> Result<()> {
let someip = recentip::configure()
.sd_unicast("192.168.1.100".parse().unwrap())
.sd_multicast_group("239.255.255.250".parse().unwrap())
.start().await?;
let found_service = someip.find(0x1234).await?;
// Fire-and-forget - no response expected
let method = MethodId::new(0x0010).unwrap();
found_service.fire_and_forget(method, b"log: button pressed").await?;
Ok(())
}§Server Side
use recentip::prelude::*;
use recentip::handle::ServiceEvent;
#[tokio::main]
async fn main() -> Result<()> {
let someip = recentip::configure()
.sd_unicast("192.168.1.100".parse().unwrap())
.sd_multicast_group("239.255.255.250".parse().unwrap())
.start().await?;
let mut offering = someip
.offer(0x1234, InstanceId::Id(0x0001))
.version(1, 0)
.start()
.await?;
while let Some(event) = offering.next().await {
if let ServiceEvent::FireForget { method, payload, .. } = event {
// No responder - just process the message
println!("Fire-and-forget 0x{:04x}: {:?}",
method.value(),
String::from_utf8_lossy(&payload)
);
}
}
Ok(())
}§Error Responses
Send error responses for failed requests:
use recentip::prelude::*;
use recentip::handle::ServiceEvent;
#[tokio::main]
async fn main() -> Result<()> {
let someip = recentip::configure()
.sd_unicast("192.168.1.100".parse().unwrap())
.sd_multicast_group("239.255.255.250".parse().unwrap())
.start().await?;
let mut offering = someip
.offer(0x1234, InstanceId::Id(0x0001))
.version(1, 0)
.start()
.await?;
while let Some(event) = offering.next().await {
if let ServiceEvent::Call { method, payload, responder, .. } = event {
if payload.is_empty() {
// Send error response
responder.reply_error(ApplicationError::MalformedMessage)?;
} else {
responder.reply(b"OK")?;
}
}
}
Ok(())
}